26 #include <Classes.hpp>
27 #include <Controls.hpp>
28 #include <StdCtrls.hpp>
30 #include <Buttons.hpp>
31 #include <ExtCtrls.hpp>
33 #include <Dialogs.hpp>
34 #include <Graphics.hpp>
35 #include <ComCtrls.hpp>
52 #pragma package(smart_init)
71 TTrain::TTrain(
int Caller,
int RearStartElementIn,
int RearStartExitPosIn, AnsiString InputCode,
int StartSpeedIn,
int MassIn,
double MaxRunningSpeedIn,
72 double MaxBrakeRateIn,
double PowerAtRailIn,
TTrainMode TrainModeIn,
TTrainDataEntry *TrainDataEntryPtrIn,
int RepeatNumberIn,
int IncrementalMinutesIn,
73 int IncrementalDigitsIn,
int SignallerMaxSpeedIn) : RearStartElement(RearStartElementIn), RearStartExitPos(RearStartExitPosIn), HeadCode(InputCode),
74 StartSpeed(StartSpeedIn), Mass(MassIn), MaxRunningSpeed(MaxRunningSpeedIn), MaxBrakeRate(MaxBrakeRateIn), PowerAtRail(PowerAtRailIn),
75 TrainMode(TrainModeIn), TrainDataEntryPtr(TrainDataEntryPtrIn), RepeatNumber(RepeatNumberIn), IncrementalMinutes(IncrementalMinutesIn),
76 IncrementalDigits(IncrementalDigitsIn), SignallerMaxSpeed(SignallerMaxSpeedIn)
87 AnsiString(RearStartExitPosIn) +
"," + AnsiString(InputCode) +
"," + AnsiString(StartSpeedIn) +
"," + AnsiString(MassIn) +
"," +
88 AnsiString(TrainModeIn));
134 for(
int x = 0; x < 4; x++)
143 for(
int x = 0; x < 4; x++)
152 for(
int x = 0; x < 4; x++)
157 for(
int x = 0; x < 4; x++)
161 for(
int x = 0; x < 3; x++)
198 for(
int x = 0; x < 4; x++)
252 throw Exception(
"Error in attempting to delete FrontCodePtr");
256 for(
int x = 0; x < 4; x++)
260 throw Exception(
"Error in attempting to delete BackgroundPtr[" + AnsiString(x) +
"]");
265 for(
int x = 0; x < 4; x++)
269 throw Exception(
"Error in attempting to delete HeadCodeGrPtr[" + AnsiString(x) +
"]");
298 int NextElementPosition, NextEntryPos, ElementLength, SpeedLimit;
364 bool TempDerail =
false;
410 else if((NextElementPosition > -1) && (NextEntryPos > -1))
481 throw Exception(
"Error, LeadElement Exit Connection is NotSet");
491 for(
int x = 0; x < 4; x++)
498 for(
int x = 0; x < 4; x++)
759 int LockedVectorNumber;
1009 if(BufferLocation ==
"")
1014 if((BufferLocation ==
"") || (BufferLocation != ExpectedLocation))
1076 int NextElementPosition, NextEntryPos;
1100 NextElementPosition = -1;
1103 if((NextElementPosition > -1) && (NextEntryPos > -1))
1221 AnsiString StationName;
1232 throw Exception(
"Error - Stopped at through station but neither lead nor mid elements have a name");
1245 if((NextElementPosition > -1) && (NextEntryPos > -1))
1376 if(TIFEntryPos == 0)
1412 if(NextElementPosition > -1)
1449 AnsiString Loc =
"";
1450 bool LocNamed =
false;
1479 Loc =
"outside railway";
1511 NextElementPosition = -1;
1522 if((NextElementPosition > -1) && (NextEntryPos > -1) && !
SPADFlag)
1540 if((NextElementPosition > -1) && (NextEntryPos > -1))
1578 FirstPair.second).
GetELink() == TempELink))
1583 SecondPair.second).
GetELink() == TempELink))
1597 FirstPair.second).
GetELink() == TempELink))
1602 SecondPair.second).
GetELink() == TempELink))
1616 FirstPair.second).
GetELink() == TempELink))
1621 SecondPair.second).
GetELink() == TempELink))
1651 ContinuationAutoSigEntry.
RouteNumber = RouteNumber;
1654 int NewLastElement = 0, NewLastExitPos = 0;
1672 if(NewLastElement == -1)
1675 throw Exception(
"Error, Connection = -1 in Continuation loop in UpdateTrain");
1678 if(NewLastExitPos == -1)
1680 throw Exception(
"Error, ConnLinkPos = -1 in Continuation loop in UpdateTrain");
1682 LastElement = NewLastElement;
1683 LastExitPos = NewLastExitPos;
1686 if(CumDistance < 1200)
1692 int FirstDistance = 0;
1693 if(CumDistance >= 1200)
1695 FirstDistance = 100;
1699 FirstDistance = 1200 - CumDistance;
1701 if(FirstDistance < 100)
1703 FirstDistance = 100;
1729 if(VectorIT->RouteNumber == RouteNumber)
1776 LockedVectorNumber)))
1935 for(
int x = 0; x < 4; x++)
1942 for(
int x = 0; x < 4; x++)
1968 if((LeadElementTrainID > -1) && (LeadElementTrainID !=
TrainID))
1973 if(OtherTrainEntryPos == -1)
1975 throw Exception(
"Error - OtherTrainEntryPos not set");
1994 int OtherTrainID = -1;
1995 if((MidExitLinkNum == 1) || (MidExitLinkNum == 3) || (MidExitLinkNum == 7) || (MidExitLinkNum == 9))
2086 bool StopRequired =
false;
2099 int NextElementEntryPos = -1;
2100 int NextElementExitPos = -1;
2101 bool TrainOnNextElement =
false;
2102 bool StopSignalAtNextElement =
false;
2103 if(ForwardConnection)
2111 StopSignalAtNextElement = ((NextTrackElement.
Config[NextElementExitPos] ==
Signal) && (NextTrackElement.
Attribute == 0));
2113 if(TrainAtStopLinkPos1 || TrainAtStopLinkPos2 || (ForwardConnection && (TrainOnNextElement || StopSignalAtNextElement)))
2168 throw Exception(
"Error, Straddle shouldn't be LeadMid prior to resetting at exit from UpdateTrain");
2381 if(Code.Length() != 4)
2385 for(
int x = 1; x < 5; x++)
2392 for(
int x = 0; x < 4; x++)
2556 throw Exception(
"Error in GetOffsetValues - Link value wrong");
2569 if((EntryLink == 1) || (EntryLink == 2) || (EntryLink == 4) || (EntryLink == 7))
2584 AnsiString(
VOffset) +
"," + AnsiString(Element) +
"," + AnsiString(EntryPos) +
"," +
HeadCode);
2593 TRect SourceRect, DestRect;
2595 DestRect.init(0, 0, 8, 8);
2598 Graphics::TBitmap *TempGraphic =
new Graphics::TBitmap;
2600 TempGraphic->PixelFormat = pf8bit;
2601 TempGraphic->Width = 16;
2602 TempGraphic->Height = 16;
2608 TempGraphic->Transparent =
true;
2612 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2613 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2619 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2627 else if(TempElement.
SpeedTag == 89)
2631 else if(TempElement.
SpeedTag == 90)
2635 else if(TempElement.
SpeedTag == 91)
2639 else if(TempElement.
SpeedTag == 92)
2643 else if(TempElement.
SpeedTag == 93)
2647 else if(TempElement.
SpeedTag == 94)
2651 else if(TempElement.
SpeedTag == 95)
2655 TempGraphic->Transparent =
true;
2659 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2660 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2662 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2669 for(
int x = 0; x < 40; x++)
2684 TempGraphic->Transparent =
true;
2688 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2689 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2691 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2705 TempGraphic->Transparent =
true;
2709 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2710 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2714 TempGraphic->Canvas->Draw(0, 0, TempElement.
GraphicPtr);
2717 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2722 TempGraphic->Transparent =
true;
2726 int BDVectorPos = -1;
2735 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2740 TempGraphic->Transparent =
true;
2744 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2745 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2747 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2753 TempGraphic->Transparent =
true;
2757 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2758 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2760 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
3026 throw Exception(
"Error, same train on two different bridge tracks");
3072 AnsiString(EntryPos) +
"," +
HeadCode);
3089 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in SetTrainElementID");
3108 AnsiString(EntryPos) +
"," +
HeadCode);
3117 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in ResetTrainElementID");
3150 AnsiString(ElementEntryPos) +
"," + AnsiString(
HOffset) +
"," + AnsiString(
VOffset) +
"," + AnsiString(StraddleValue) +
"," +
HeadCode);
3151 int LockedVectorNumber;
3164 TRect SourceRect, DestRect;
3165 DestRect.init(0, 0, 8, 8);
3172 int FirstELink, SecondELink = -1;
3175 if(RoutePair2.first > -1)
3184 if(SecondELink == -1)
3186 throw Exception(
"Error - Second ELink should be set but isn't in PlotAlternativeTrackRouteGraphic [1]");
3191 throw Exception(
"Error - First & Second ELinks have same value in PlotAlternativeTrackRouteGraphic");
3201 Graphics::TBitmap *DestGraphic =
new Graphics::TBitmap;
3202 DestGraphic->PixelFormat = pf8bit;
3203 DestGraphic->Width = 8;
3204 DestGraphic->Height = 8;
3205 DestGraphic->Transparent =
true;
3208 DestGraphic->Canvas->CopyRect(DestRect, RouteElement.
GetRouteEXGraphicPtr()->Canvas, SourceRect);
3217 PrefDirElement, LockedVectorNumber))
3232 if(ElementEntryPos > 1)
3254 AnsiString(EntryPos) +
"," +
HeadCode);
3256 bool WrongRoute =
false;
3282 int LinkNumber = TrackElement.
Link[EntryPos];
3283 if((LinkNumber == 1) || (LinkNumber == 3) || (LinkNumber == 7) || (LinkNumber == 9))
3288 bool LogActionErrorCalled =
false;
3298 LogActionErrorCalled =
true;
3315 else if(LinkNumber == 3)
3323 LogActionErrorCalled =
true;
3340 else if(LinkNumber == 7)
3348 LogActionErrorCalled =
true;
3365 else if(LinkNumber == 9)
3373 LogActionErrorCalled =
true;
3405 else if((RouteElement.
GetELinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
3410 else if((RouteElement.
GetELinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
3420 else if((RouteElement.
GetXLinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
3425 else if((RouteElement.
GetXLinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
3434 throw Exception(
"Error, Element in route but no route found in CheckAndCancelRouteForWrongEndEntry");
3455 bool ColourError =
false, ColourError2 =
false;
3460 ColourError2 =
true;
3462 for(
int x = 0; x < 4; x++)
3467 ColourError2 =
true;
3473 "ERROR: Colour depth insufficient to display train colours properly. Please ensure that the 'safe' (web) palette of 256 colours can be displayed");
3477 for(
int x = 0; x < 4; x++)
3564 AnsiString(EntryPos) +
"," +
HeadCode);
3565 int EntryHalfLength, CurrentElementHalfLength, NextElementHalfLength, CumulativeLength = 0, CurrentTrackVectorPosition = TrackVectorPosition;
3566 int DistanceAtHalfBraking, DistanceAtThreeQuarterBraking, ExitPos, NextTrackVectorPosition, NextEntryPos;
3567 bool RedSignalFlag =
false, BuffersFlag =
false, StationFlag =
false, BuffersOrContinuationNowFlag =
false, ContinuationNextFlag =
false,
3568 TrainInFrontInSignallerModeFlag =
false;
3569 double LimitingSpeed, FrontElementMaxSpeed, MaxExitSpeedAtHalfBrakingSquared, MaxExitSpeedAtHalfBraking, NextSpeedLimit, TempBrakeRate;
3570 double ExitSpeedHalfSquared, ExitSpeedFullSquared;
3571 bool SignallerStopRequired =
false;
3582 if(CurrentTrackVectorPosition > -1)
3586 if((EntryPos == 0) || (EntryPos == 2))
3599 else if(EntryPos == 1)
3623 EntryHalfLength = CurrentElementHalfLength;
3628 throw Exception(
"Error - CurrentTrackVectorPosition < 0 in SetTrainMovementValues");
3632 throw Exception(
"Error - HalfLength or SpeedLimit < 0 in SetTrainMovementValues");
3679 FrontElementMaxSpeed = LimitingSpeed;
3714 double ExitSpeedAtMaxBraking;
3719 ExitSpeedAtMaxBraking = 0;
3729 if(ExitSpeedAtMaxBraking > LimitingSpeed)
3731 SpeedToUse = ExitSpeedAtMaxBraking;
3735 SpeedToUse = LimitingSpeed;
3750 RedSignalFlag =
false;
3751 BuffersFlag =
false;
3752 StationFlag =
false;
3753 BuffersOrContinuationNowFlag =
false;
3754 ContinuationNextFlag =
false;
3757 CumulativeLength += (2 * CurrentElementHalfLength);
3760 SignallerStopRequired =
true;
3782 bool StopRequired =
false;
3796 StationFlag =
false;
3802 BuffersOrContinuationNowFlag =
true;
3804 if(!BuffersOrContinuationNowFlag && !BuffersFlag && !StationFlag)
3808 if((EntryPos == 0) || (EntryPos == 2))
3830 if(NextTrackVectorPosition > -1)
3835 if((NextEntryPos == 0) || (NextEntryPos == 2))
3848 else if(NextEntryPos == 1)
3861 if(NextEntryPos > 1)
3875 throw Exception(
"Error - Trying to access NextTrackVectorPosition when none present in SetTrainMovementValues");
3887 RedSignalFlag =
true;
3909 TrainInFrontInSignallerModeFlag =
true;
3933 if(RedSignalFlag || BuffersFlag || StationFlag || TrainInFrontInSignallerModeFlag || SignallerStopRequired ||
StepForwardFlag)
3945 double MaxHalfSpeed;
3949 if(MaxHalfSpeedAtHalfBraking > FrontElementMaxSpeed)
3951 MaxHalfSpeed = FrontElementMaxSpeed;
3955 MaxHalfSpeed = MaxHalfSpeedAtHalfBraking;
3963 bool HalfSpeedLimited =
false;
3967 HalfSpeedLimited =
true;
3997 if(HalfSpeedLimited)
4022 if(SignallerStopRequired)
4038 int TempMaxExitSpeed;
4041 if(MaxExitSpeedAtHalfBrakingSquared < 10)
4043 MaxExitSpeedAtHalfBraking = 0;
4047 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
4051 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
4053 TempMaxExitSpeed = FrontElementMaxSpeed;
4057 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
4069 if(ExitSpeedHalfSquared < 10)
4079 if(ExitSpeedFullSquared < 10)
4151 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4152 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4176 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4177 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4187 if(!BuffersOrContinuationNowFlag)
4189 if(NextSpeedLimit < LimitingSpeed)
4191 LimitingSpeed = NextSpeedLimit;
4195 int TempMaxExitSpeed;
4199 if(MaxExitSpeedAtHalfBrakingSquared < 10)
4201 MaxExitSpeedAtHalfBraking = 0;
4205 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
4207 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
4209 TempMaxExitSpeed = FrontElementMaxSpeed;
4213 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
4224 TempBrakeRate = ((
EntrySpeed *
EntrySpeed) - (LimitingSpeed * LimitingSpeed)) / 3.6 / 3.6 / 2 / CumulativeLength;
4237 if(!BuffersOrContinuationNowFlag)
4239 CurrentTrackVectorPosition = NextTrackVectorPosition;
4240 EntryPos = NextEntryPos;
4241 CurrentElementHalfLength = NextElementHalfLength;
4244 ContinuationNextFlag =
true;
4248 while(((CumulativeLength -
FrontElementLength) < DistanceAtHalfBraking) && ((!BuffersOrContinuationNowFlag && !ContinuationNextFlag) ||
4268 if(ExitSpeedHalfSquared < 10)
4278 if(ExitSpeedFullSquared < 10)
4341 double DeltaExitTimeToMaxInSecs;
4342 double DistanceToMax;
4351 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
4353 DistanceToMax = EntryHalfLength;
4356 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4357 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4374 double DeltaExitTimeToMaxInSecs;
4375 double DistanceToMax;
4384 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
4386 DistanceToMax = EntryHalfLength / 2;
4389 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4390 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4401 if(ExitSpeedHalfSquared < 10)
4411 if(ExitSpeedFullSquared < 10)
4430 if((EntryPos == 0) || (EntryPos == 2))
4452 if(NextTrackVectorPosition > -1)
4454 int NextElementLength;
4455 if(NextEntryPos > 1)
4463 double NextStoppingSpeed = sqrt(3.6 * 3.6 * 2 *
BrakeRate * NextElementLength);
4650 int ElementCount = 0;
4658 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition;
4676 CurrentTrackVectorPosition).
Attribute != 4))
4716 if((EntryPos == 0) || (EntryPos == 2))
4738 CurrentTrackVectorPosition = NextTrackVectorPosition;
4739 EntryPos = NextEntryPos;
4741 if(ElementCount > 1000)
4769 throw Exception(
"Error - failed to set ReturnVal in ClearToNextSignal()");
4794 bool PlatformFoundFlag =
false, StopRequired =
false, SkipRouteCheck =
false, RouteOrPartRouteSet =
false;
4795 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition, ElementNumber = 0, Distance = 0;
4796 int RouteStartPosition;
4798 int PlatformPosition;
4800 int EntryPos =
LeadEntryPos, ExitPos, NextEntryPos, RouteID;
4816 if(Distance > (4000 + LeadElementDistance))
4839 if(OtherTrain.
LeadElement == CurrentTrackVectorPosition)
4842 if((OtherCommand ==
"Fjo") || (OtherCommand ==
"jbo") || (OtherCommand ==
"cdt") || (OtherCommand ==
"Frh") ||
4888 if(!PlatformFoundFlag)
4890 PlatformPosition = CurrentTrackVectorPosition;
4893 PlatformFoundFlag =
true;
4909 if((EntryPos == 0) || (EntryPos == 2))
4953 if(ElementNumber < 2)
4955 SkipRouteCheck =
true;
4959 SkipRouteCheck =
false;
4961 if(ElementNumber == 1)
4963 RouteStartPosition = CurrentTrackVectorPosition;
4973 if(ElementNumber > 1)
4977 RouteOrPartRouteSet =
true;
4981 RouteOrPartRouteSet =
false;
4984 if(!SkipRouteCheck && !RouteOrPartRouteSet)
4991 int ExitLink = CurrentTrackElement.
Link[ExitPos];
4992 if((ExitLink == 1) || (ExitLink == 3) || (ExitLink == 7) || (ExitLink == 9))
5004 Distance += CurrentTrackElement.
Length01;
5008 Distance += CurrentTrackElement.
Length23;
5010 NextTrackVectorPosition = CurrentTrackElement.
Conn[ExitPos];
5011 NextEntryPos = CurrentTrackElement.
ConnLinkPos[ExitPos];
5012 CurrentTrackVectorPosition = NextTrackVectorPosition;
5013 EntryPos = NextEntryPos;
5050 return(RepeatHeadCode);
5072 bool FrontValid =
false, RearValid =
false;
5073 TTrackElement FrontAdjacentTrackElement, RearAdjacentTrackElement;
5077 TrainToBeJoinedBy = NULL;
5091 int TrainToBeJoinedByID = -1;
5112 if((TrainToBeJoinedByID < 0) && RearValid)
5131 if(TrainToBeJoinedByID < 0)
5133 TrainToBeJoinedBy = NULL;
5138 if(!TrainToBeJoinedBy->
Stopped())
5140 TrainToBeJoinedBy = NULL;
5151 TDateTime TimetableNonRepeatTime,
bool Warning)
5186 AnsiString(ActionType) +
"," + LocationName +
"," +
HeadCode);
5187 AnsiString BaseLog =
"", WarningBaseLog =
"", PerfLog =
"", ActionLog =
"";
5188 int IntMinsLate = 0;
5193 ActionLog =
" arrived at ";
5202 ActionLog =
" terminated at ";
5207 ActionLog =
" departed from ";
5209 if(ActionType ==
Pass)
5211 ActionLog =
" passed ";
5215 ActionLog =
" created at ";
5217 if(ActionType ==
Enter)
5219 ActionLog =
" entered railway at ";
5221 if(ActionType ==
Leave)
5223 ActionLog =
" left railway at ";
5227 ActionLog =
" split from front to ";
5231 ActionLog =
" split from rear to ";
5235 ActionLog =
" joined by ";
5239 ActionLog =
" changed direction at ";
5243 ActionLog =
" became new service ";
5247 ActionLog =
" taken under signaller control at ";
5251 ActionLog =
" restored to timetable control at ";
5257 ActionLog =
" REMOVED FROM RAILWAY DUE TO CRASH at ";
5261 ActionLog =
" REMOVED FROM RAILWAY DUE TO DERAILMENT at ";
5265 ActionLog =
" REMOVED FROM RAILWAY at ";
5270 ActionLog =
" received signaller authority to proceed";
5274 ActionLog =
" received signaller authority to step forward";
5278 ActionLog =
" changed direction under signaller control at ";
5282 ActionLog =
" received signaller authority to pass red signal";
5286 ActionLog =
" received signaller instruction to stop";
5290 ActionLog =
" stopped on signaller instruction ";
5294 ActionLog =
" joined under signaller control by ";
5298 ActionLog =
" suffered an onboard power failure at ";
5302 ActionLog =
" failure repaired at ";
5306 ActionLog =
" left railway under signaller control at ";
5308 if(OtherHeadCode !=
"")
5310 OtherHeadCode +=
" at ";
5317 WarningBaseLog =
HeadCode + ActionLog + OtherHeadCode + LocationName;
5323 bool TimePerformance =
true;
5331 TimePerformance =
false;
5335 double MinsLate = ((double)(ActualTime -
GetTrainTime(1, TimetableNonRepeatTime))) * 1440;
5337 if(ActionType ==
Pass)
5351 IntMinsLate = int(ceil(MinsLate));
5355 IntMinsLate = int(floor(MinsLate));
5357 if(IntMinsLate == 0)
5359 PerfLog =
" on time";
5361 else if(IntMinsLate == 1)
5363 PerfLog =
" 1 minute late";
5365 else if(IntMinsLate == -1)
5367 PerfLog =
" 1 minute early";
5369 else if(IntMinsLate > 1)
5371 PerfLog =
" " + AnsiString(IntMinsLate) +
" minutes late";
5373 else if(IntMinsLate < -1)
5375 int PosIntMinsLate = -IntMinsLate;
5376 PerfLog =
" " + AnsiString(PosIntMinsLate) +
" minutes early";
5378 if(LocationName.Pos(
'-') > 0)
5380 PerfLog =
"," + PerfLog;
5394 if((ActionType ==
Arrive) && (IntMinsLate == 0))
5398 else if((ActionType ==
Arrive) && (IntMinsLate > 0))
5403 else if((ActionType ==
Arrive) && (IntMinsLate < 0))
5409 else if((ActionType ==
Pass) && (IntMinsLate == 0))
5413 else if((ActionType ==
Pass) && (IntMinsLate > 0))
5418 else if((ActionType ==
Pass) && (IntMinsLate < 0))
5424 else if((ActionType ==
Leave) && (IntMinsLate == 0))
5428 else if((ActionType ==
Leave) && (IntMinsLate > 0))
5433 else if((ActionType ==
Leave) && (IntMinsLate < 0))
5439 else if((ActionType ==
Depart) && (IntMinsLate == 0))
5443 else if((ActionType ==
Depart) && (IntMinsLate > 0))
5462 AnsiString LocName =
"";
5529 if(LocationName ==
"")
5533 int FirstNamedElementPos, SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos;
5534 int RearTrainRearPosition, RearTrainFrontPosition, RearTrainExitPos;
5535 int FrontTrainRearPosition, FrontTrainFrontPosition, FrontTrainExitPos;
5539 if(LocationName !=
"")
5547 SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos))
5552 SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos))
5566 int LeadPosA = FirstNamedElementPos;
5567 int LeadPosB = FirstNamedLinkedElementPos;
5568 int LeadPosC = SecondNamedElementPos;
5569 int LeadPosD = SecondNamedLinkedElementPos;
5571 int LeadNumAtLoc = 0;
5588 if(LeadNumAtLoc < 4)
5592 SecondNamedLinkedElementPos))
5594 FirstNamedElementPos = LeadPosA;
5595 FirstNamedLinkedElementPos = LeadPosB;
5596 SecondNamedElementPos = LeadPosC;
5597 SecondNamedLinkedElementPos = LeadPosD;
5601 int MidNumAtLoc = 0;
5618 if(LeadNumAtLoc > MidNumAtLoc)
5621 FirstNamedElementPos = LeadPosA;
5622 FirstNamedLinkedElementPos = LeadPosB;
5623 SecondNamedElementPos = LeadPosC;
5624 SecondNamedLinkedElementPos = LeadPosD;
5638 throw Exception(
"Error - LocationName not set in FrontTrainSplit");
5648 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
5649 FrontTrainRearPosition = FirstNamedElementPos;
5650 RearTrainFrontPosition = SecondNamedElementPos;
5651 RearTrainRearPosition = SecondNamedLinkedElementPos;
5655 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
5656 FrontTrainRearPosition = SecondNamedElementPos;
5657 RearTrainFrontPosition = FirstNamedElementPos;
5658 RearTrainRearPosition = FirstNamedLinkedElementPos;
5665 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
5666 FrontTrainRearPosition = SecondNamedElementPos;
5667 RearTrainFrontPosition = FirstNamedElementPos;
5668 RearTrainRearPosition = FirstNamedLinkedElementPos;
5672 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
5673 FrontTrainRearPosition = FirstNamedElementPos;
5674 RearTrainFrontPosition = SecondNamedElementPos;
5675 RearTrainRearPosition = SecondNamedLinkedElementPos;
5678 RearTrainExitPos = -1;
5679 for(
int x = 0; x < 4; x++)
5683 RearTrainExitPos = x;
5687 if(RearTrainExitPos == -1)
5689 throw Exception(
"Error - RearTrainRearPosition not linked to RearTrainFrontPosition in FrontTrainSplit");
5691 FrontTrainExitPos = -1;
5692 for(
int x = 0; x < 4; x++)
5696 FrontTrainExitPos = x;
5700 if(FrontTrainExitPos == -1)
5702 throw Exception(
"Error - FrontTrainRearPosition not linked to FrontTrainFrontPosition in FrontTrainSplit");
5705 int TrainIDOnRearOfRearTrain, TrainIDOnFrontOfRearTrain, TrainIDOnRearOfFrontTrain, TrainIDOnFrontOfFrontTrain;
5712 else if((RearMostElement.
TrackType ==
Bridge) && (RearTrainExitPos < 2))
5732 else if((FrontMostElement.
TrackType ==
Bridge) && (FrontTrainExitPos < 2))
5740 if(((TrainIDOnRearOfRearTrain > -1) && (TrainIDOnRearOfRearTrain !=
TrainID)) || ((TrainIDOnFrontOfRearTrain > -1) && (TrainIDOnFrontOfRearTrain !=
TrainID)
5741 ) || ((TrainIDOnRearOfFrontTrain > -1) && (TrainIDOnRearOfFrontTrain !=
TrainID)) ||
5742 ((TrainIDOnFrontOfFrontTrain > -1) && (TrainIDOnFrontOfFrontTrain !=
TrainID)))
5839 if(LocationName ==
"")
5843 int FirstNamedElementPos, SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos;
5844 int RearTrainRearPosition, RearTrainFrontPosition, RearTrainExitPos;
5845 int FrontTrainRearPosition, FrontTrainFrontPosition, FrontTrainExitPos;
5849 if(LocationName !=
"")
5856 SecondNamedLinkedElementPos))
5860 SecondNamedLinkedElementPos))
5874 int LeadPosA = FirstNamedElementPos;
5875 int LeadPosB = FirstNamedLinkedElementPos;
5876 int LeadPosC = SecondNamedElementPos;
5877 int LeadPosD = SecondNamedLinkedElementPos;
5879 int LeadNumAtLoc = 0;
5896 if(LeadNumAtLoc < 4)
5900 SecondNamedLinkedElementPos))
5902 FirstNamedElementPos = LeadPosA;
5903 FirstNamedLinkedElementPos = LeadPosB;
5904 SecondNamedElementPos = LeadPosC;
5905 SecondNamedLinkedElementPos = LeadPosD;
5909 int MidNumAtLoc = 0;
5926 if(LeadNumAtLoc > MidNumAtLoc)
5929 FirstNamedElementPos = LeadPosA;
5930 FirstNamedLinkedElementPos = LeadPosB;
5931 SecondNamedElementPos = LeadPosC;
5932 SecondNamedLinkedElementPos = LeadPosD;
5946 throw Exception(
"Error - LocationName not set in RearTrainSplit");
5956 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
5957 FrontTrainRearPosition = FirstNamedElementPos;
5958 RearTrainFrontPosition = SecondNamedElementPos;
5959 RearTrainRearPosition = SecondNamedLinkedElementPos;
5963 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
5964 FrontTrainRearPosition = SecondNamedElementPos;
5965 RearTrainFrontPosition = FirstNamedElementPos;
5966 RearTrainRearPosition = FirstNamedLinkedElementPos;
5973 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
5974 FrontTrainRearPosition = SecondNamedElementPos;
5975 RearTrainFrontPosition = FirstNamedElementPos;
5976 RearTrainRearPosition = FirstNamedLinkedElementPos;
5980 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
5981 FrontTrainRearPosition = FirstNamedElementPos;
5982 RearTrainFrontPosition = SecondNamedElementPos;
5983 RearTrainRearPosition = SecondNamedLinkedElementPos;
5986 RearTrainExitPos = -1;
5987 for(
int x = 0; x < 4; x++)
5991 RearTrainExitPos = x;
5995 if(RearTrainExitPos == -1)
5997 throw Exception(
"Error - RearTrainRearPosition not linked to RearTrainFrontPosition in RearTrainSplit");
5999 FrontTrainExitPos = -1;
6000 for(
int x = 0; x < 4; x++)
6004 FrontTrainExitPos = x;
6008 if(FrontTrainExitPos == -1)
6010 throw Exception(
"Error - FrontTrainRearPosition not linked to FrontTrainFrontPosition in RearTrainSplit");
6013 int TrainIDOnRearOfRearTrain, TrainIDOnFrontOfRearTrain, TrainIDOnRearOfFrontTrain, TrainIDOnFrontOfFrontTrain;
6020 else if((RearMostElement.
TrackType ==
Bridge) && (RearTrainExitPos < 2))
6040 else if((FrontMostElement.
TrackType ==
Bridge) && (FrontTrainExitPos < 2))
6048 if(((TrainIDOnRearOfRearTrain > -1) && (TrainIDOnRearOfRearTrain !=
TrainID)) || ((TrainIDOnFrontOfRearTrain > -1) && (TrainIDOnFrontOfRearTrain !=
TrainID)
6049 ) || ((TrainIDOnRearOfFrontTrain > -1) && (TrainIDOnRearOfFrontTrain !=
TrainID)) ||
6050 ((TrainIDOnFrontOfFrontTrain > -1) && (TrainIDOnFrontOfFrontTrain !=
TrainID)))
6189 TTrain *TrainToBeJoinedBy;
6222 double OtherBrakeForce = TrainToBeJoinedBy->
MaxBrakeRate * TrainToBeJoinedBy->
Mass;
6224 double CombinedBrakeRate = (OtherBrakeForce + OwnBrakeForce) / (TrainToBeJoinedBy->
Mass +
Mass);
6284 int RouteNumber = -1;
6292 bool FirstPass =
true;
6297 if(FirstPass && (TVPos2 != FirstRouteElementVecPos))
6404 for(
int x = 0; x < IncNum; x++)
6437 else if(Ptr->
Command ==
"jbo")
6448 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
6454 bool IncludeFER =
false;
6462 if(!IncludeFER && (Ptr->
Command ==
"Fer"))
6467 else if(IncludeFER && (Ptr->
Command ==
"Fer"))
6478 else if(Ptr->
Command ==
"Fjo")
6484 else if(Ptr->
Command ==
"Frh")
6494 else if(Ptr->
Command ==
"Frh-sh")
6545 else if(Ptr->
Command ==
"jbo")
6550 else if(Ptr->
Command ==
"cdt")
6558 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
6944 int RouteNumber = -1;
6952 bool FirstPass =
true;
6957 if(FirstPass && (TVPos2 != FirstRouteElementVecPos))
6985 ",FloatingLabelNextString" +
"," +
HeadCode);
6986 AnsiString RetStr =
"", LocationName =
"";
6990 throw Exception(
"Error - start entry in FloatingLabelNextString");
7034 else if(Ptr->
Command ==
"Fns")
7040 else if(Ptr->
Command ==
"F-nshs")
7071 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7073 else if(Ptr->
Command ==
"Frh")
7075 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7077 else if(Ptr->
Command ==
"Fer")
7079 AnsiString AllowedExits =
"";
7082 else if(Ptr->
Command ==
"Fjo")
7087 else if(Ptr->
Command ==
"jbo")
7092 else if(Ptr->
Command ==
"fsp")
7097 else if(Ptr->
Command ==
"rsp")
7102 else if(Ptr->
Command ==
"cdt")
7115 + AnsiString(RptNum) +
",GetNewServiceDepartureInfo," +
HeadCode);
7116 AnsiString DepTime =
"", EventTime =
"";
7117 bool CDTFlag =
false;
7119 AnsiString CurrentLocation = NewServiceAV.at(0).LocationName;
7120 AnsiString TowardsLocation =
"";
7123 if((AVI->LocationName != CurrentLocation) && (AVI->LocationName !=
"") && (TowardsLocation ==
""))
7125 TowardsLocation = AVI->LocationName;
7127 else if((AVI->Command ==
"Fer") && (TowardsLocation ==
"") && !AVI->ExitList.empty())
7136 TowardsLocation = AnsiString(
"track element ID ") + TE.
ElementID;
7142 if(AVI->Command ==
"cdt")
7147 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
7150 RetStr +=
"\nNew service splits at " + EventTime;
7154 if(AVI->Command ==
"jbo")
7157 RetStr +=
"\nNew service joined by " + AVI->OtherHeadCode +
" at " + EventTime;
7161 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
7166 if(TowardsLocation !=
"")
7168 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at " + DepTime;
7172 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
7177 if(TowardsLocation !=
"")
7179 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at " + DepTime;
7183 RetStr +=
"\nNew service departs at " + DepTime;
7201 ",FloatingTimetableString" +
"," +
HeadCode);
7202 AnsiString RetStr =
"", PartStr =
"";
7204 bool SkipDep =
false, SkipDepActedOn =
false;
7210 throw Exception(
"Error - start entry in FloatingTimetableString");
7213 bool FirstPass =
true;
7226 AnsiString TrainLoc =
"";
7272 AnsiString TrainLoc =
"";
7312 else if(Ptr->
Command ==
"Fns")
7318 else if(Ptr->
Command ==
"F-nshs")
7351 else if(Ptr->
Command ==
"Frh")
7355 else if(Ptr->
Command ==
"Fer")
7357 AnsiString AllowedExits =
"";
7360 else if(Ptr->
Command ==
"Fjo")
7365 else if(Ptr->
Command ==
"jbo")
7370 else if(Ptr->
Command ==
"fsp")
7375 else if(Ptr->
Command ==
"rsp")
7380 else if(Ptr->
Command ==
"cdt")
7386 RetStr = RetStr +
'\n' + PartStr;
7400 SkipDepActedOn =
true;
7411 RetStr =
"Timetable finished";
7415 RetStr =
"No timetable";
7572 bool ForwardHeadCode;
7576 ForwardHeadCode =
true;
7581 ForwardHeadCode =
false;
7724 if(ColourNumber == 0)
7728 else if(ColourNumber == 1)
7732 else if(ColourNumber == 2)
7736 else if(ColourNumber == 3)
7740 else if(ColourNumber == 4)
7744 else if(ColourNumber == 5)
7748 else if(ColourNumber == 6)
7752 else if(ColourNumber == 7)
7756 else if(ColourNumber == 8)
7760 else if(ColourNumber == 9)
7764 else if(ColourNumber == 10)
7768 else if(ColourNumber == 11)
7772 else if(ColourNumber == 12)
7776 else if(ColourNumber == 13)
7780 else if(ColourNumber == 14)
7792 for(
int x = 0; x < 4; x++)
7799 for(
int x = 0; x < 4; x++)
7884 if((LocationAndMarker[1] !=
'*') && (LocationAndMarker.Length() > 6))
7887 AnsiString Location = LocationAndMarker.SubString(1, LocationAndMarker.Length() - 6);
7888 bool GiveMessagesFalse =
false;
7889 bool CheckLocationsExistInRailwayTrue =
true;
7896 AnsiString Marker = LocationAndMarker.SubString(LocationAndMarker.Length() - 5, 6);
7899 if(Marker[6] ==
'1')
8364 bool HideFlashingTrain =
true;
8367 Graphics::TBitmap *SmallTrainBitmap;
8408 HideFlashingTrain =
false;
8413 HideFlashingTrain =
false;
8418 HideFlashingTrain =
false;
8423 HideFlashingTrain =
false;
8428 HideFlashingTrain =
false;
8432 if((
LeadElement > -1) && (!HideFlashingTrain || Flash))
8436 if((
MidElement > -1) && (!HideFlashingTrain || Flash))
8460 for(
int y = 0; y < 3; y++)
8464 bool FoundFlag =
false;
8475 if(IMPair.first != IMPair.second)
8502 if((LocationName ==
"") && (
MidElement > -1))
8506 if((LocationName ==
"") && (
LagElement > -1))
8510 if(LocationName ==
"")
8512 throw Exception(
"Error - Location name not set in TrainAtLocation");
8523 for(
int x = 0; x < 4; x++)
8535 for(
int x = 0; x < 4; x++)
8552 AnsiString(LinkNumber) +
"," +
HeadCode);
8604 int DistanceToRedSignal = 0, DistanceToExit = -1;
8605 float TimeToAct = 0, LastTimeToExit =
TimeToExit;
8609 float MinsEarly = 0;
8610 TDateTime DepartureTime;
8611 TDateTime ArrivalTime;
8639 if(TempTTE < LastTimeToExit)
8674 if(TempTTE < LastTimeToExit)
8697 if(TempTTE < LastTimeToExit)
8727 if(TempTTE < LastTimeToExit)
8750 if(TempTTE < LastTimeToExit)
8793 float CurrentStopTime;
8794 float LaterStopTime;
8795 float RecoverableTime;
8803 if((DistanceToRedSignal == -1) && (DistanceToExit == -1))
8810 bool DistanceToRedSignalSet = (DistanceToRedSignal > -1);
8811 bool DistanceToExitSet = (DistanceToExit > -1);
8812 int GenericDistance = DistanceToRedSignal;
8813 if(DistanceToExitSet)
8815 GenericDistance = DistanceToExit;
8831 float TimeToSubtract, TotalStopTime;
8834 TimeToSubtract = RecoverableTime;
8877 if(CurrentStopTime > 0)
8879 TotalStopTime = CurrentStopTime + LaterStopTime;
8888 else if((MinsEarly > 0) && !
Stopped())
8890 TotalStopTime = LaterStopTime + MinsEarly;
8894 if(LaterStopTime == 0)
8896 TotalStopTime = CurrentStopTime;
8902 TotalStopTime = CurrentStopTime + LaterStopTime - TimeToSubtract;
8905 if(AvTrackSpeed < 30)
8909 int Speed = AvTrackSpeed;
8919 if(DistanceToRedSignalSet)
8921 TimeToAct = TotalStopTime + GenericDistance * 3.6 / 60 / Speed;
8931 TimeToExit = TotalStopTime + GenericDistance * 3.6 / 60 / Speed;
8954 if((NextEntryPos == 0) || (NextEntryPos == 2))
9081 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9123 int IncrementalMinutes = 0;
9124 int IncrementalDigits = 0;
9132 throw Exception(
"Error - Repeat entry && less than two trains for Snt entry: " + TDEntry.
HeadCode);
9167 if(AVEntry0.
Command ==
"Snt-sh")
9172 int IncrementalMinutes = 0;
9173 int IncrementalDigits = 0;
9181 throw Exception(
"Error - Repeat entry && less than two trains for Snt-sh entry: " + TDEntry.
HeadCode);
9224 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9304 AnsiString Loc =
"";
9305 bool ElementFound =
false;
9310 ElementFound =
true;
9315 ElementFound =
true;
9320 ElementFound =
true;
9349 else if(AVEntryPtr->
Command ==
"Fer")
9351 bool CorrectExit =
false;
9462 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9480 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9495 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9506 bool TTrainController::AddTrain(
int Caller,
int RearPosition,
int FrontPosition, AnsiString HeadCode,
int StartSpeed,
int Mass,
double MaxRunningSpeed,
9507 double MaxBrakeRate,
double PowerAtRail, AnsiString ModeStr,
TTrainDataEntry *TrainDataEntryPtr,
int RepeatNumber,
int IncrementalMinutes,
9508 int IncrementalDigits,
int SignallerSpeed,
bool SignallerControl,
TActionEventType &EventType)
9510 LogEvent(AnsiString(Caller) +
",AddTrain," + AnsiString(RearPosition) +
"," + AnsiString(FrontPosition) +
"," + HeadCode +
"," + AnsiString(StartSpeed) +
9511 "," + AnsiString(Mass) +
"," + ModeStr);
9513 "," + HeadCode +
"," + AnsiString(StartSpeed) +
"," + AnsiString(Mass) +
"," + ModeStr);
9515 int RearExitPos = -1;
9517 for(
int x = 0; x < 4; x++)
9524 if(RearExitPos == -1)
9526 throw Exception(
"Error, RearExit == -1 in AddTrain");
9528 bool ReportFlag =
true;
9545 if(ModeStr ==
"Timetable")
9551 if(MaxRunningSpeed < 10)
9553 MaxRunningSpeed = 10;
9555 if(SignallerSpeed < 10)
9557 SignallerSpeed = 10;
9559 TTrain *NewTrain =
new TTrain(0, RearPosition, RearExitPos, HeadCode, StartSpeed, Mass, MaxRunningSpeed, MaxBrakeRate, PowerAtRail, TrainMode,
9560 TrainDataEntryPtr, RepeatNumber, IncrementalMinutes, IncrementalDigits, SignallerSpeed);
9567 if(SignallerControl)
9597 if(!SignallerControl)
9612 if(!SignallerControl)
9623 AnsiString Loc =
"";
9640 if(!SignallerControl)
9659 int RouteNumber = -1;
9660 bool SignalsSet =
false;
9667 int RouteStartPosition;
9671 if(FirstPair.first == RouteNumber)
9673 RouteStartPosition = FirstPair.second;
9675 else if(SecondPair.first == RouteNumber)
9677 RouteStartPosition = SecondPair.second;
9681 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 1st of 2 calls to SetAllRearwardsSignals in AddTrain");
9687 else if(RouteNumber > -1)
9707 int LinkedRouteNumber = -1;
9728 int RouteStartPosition;
9732 if(FirstPair.first == RouteNumber)
9734 RouteStartPosition = FirstPair.second;
9736 else if(SecondPair.first == RouteNumber)
9738 RouteStartPosition = SecondPair.second;
9742 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 2nd of 2 calls to SetAllRearwardsSignals in AddTrain");
9748 else if(RouteNumber > -1)
9768 int LinkedRouteNumber = -1;
9789 AnsiString(TrackVectorNumber));
9792 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9801 throw Exception(
"Error, VecPos not set in EntryPos");
9803 if(
TrainVectorAt(2, VecPos).LeadElement == TrackVectorNumber)
9808 else if(
TrainVectorAt(4, VecPos).MidElement == TrackVectorNumber)
9813 else if(
TrainVectorAt(6, VecPos).LagElement == TrackVectorNumber)
9827 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9835 throw Exception(
"Error - No Train identified in TrainVectorAtIdent with ID = " + AnsiString(TrainID));
9845 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9875 AnsiString RetStr =
"", PartStr =
"";
9883 if((Ptr->Command !=
"") && (Ptr->Command[1] ==
'S'))
9891 if(Ptr->SignallerControl)
9893 RetStr =
"Train under signaller control";
9898 if(Ptr->ArrivalTime == Ptr->DepartureTime)
9909 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime != TDateTime(-1)))
9913 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime == TDateTime(-1)))
9917 else if(Ptr->FormatType ==
PassTime)
9921 else if(Ptr->Command ==
"Fns")
9927 else if(Ptr->Command ==
"F-nshs")
9930 Ptr->NonRepeatingShuttleLinkHeadCode +
" at " + Ptr->LocationName;
9937 else if((Ptr->Command ==
"Fns-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
9944 else if((Ptr->Command ==
"Fns-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
9947 Ptr->NonRepeatingShuttleLinkHeadCode, +
" at " + Ptr->LocationName;
9950 else if((Ptr->Command ==
"Frh-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
9957 else if((Ptr->Command ==
"Frh-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
9959 PartStr =
"Terminate at " + Ptr->LocationName;
9961 else if(Ptr->Command ==
"Frh")
9963 PartStr =
"Terminate at " + Ptr->LocationName;
9965 else if(Ptr->Command ==
"Fer")
9967 AnsiString AllowedExits;
9971 else if(Ptr->Command ==
"Fjo")
9974 Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
9976 else if(Ptr->Command ==
"jbo")
9979 (50, Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
9981 else if(Ptr->Command ==
"fsp")
9986 else if(Ptr->Command ==
"rsp")
9991 else if(Ptr->Command ==
"cdt")
9997 RetStr = RetStr +
'\n' + PartStr;
10005 while(Ptr < TTDEPtr->ActionVector.end() && (Count < 33) && ((Ptr->Command ==
"") || ((Ptr->Command !=
"") && (Ptr->Command[1] !=
'F'))));
10018 + AnsiString(RptNum) +
",ControllerGetNewServiceDepartureInfo," + TDEPtr->
HeadCode);
10019 AnsiString DepTime =
"", EventTime =
"";
10020 bool CDTFlag =
false;
10022 AnsiString CurrentLocation = NewServiceAV.at(0).LocationName;
10023 AnsiString TowardsLocation =
"";
10026 if((AVI->LocationName != CurrentLocation) && (AVI->LocationName !=
"") && (TowardsLocation ==
""))
10028 TowardsLocation = AVI->LocationName;
10030 else if((AVI->Command ==
"Fer") && (TowardsLocation ==
"") && !AVI->ExitList.empty())
10039 TowardsLocation = AnsiString(
"track element ID ") + TE.
ElementID;
10045 if(AVI->Command ==
"cdt")
10047 CDTFlag = !CDTFlag;
10050 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
10053 RetStr +=
"\nNew service splits at " + EventTime;
10057 if(AVI->Command ==
"jbo")
10060 RetStr +=
"\nNew service joined by " + AVI->OtherHeadCode +
" at " + EventTime;
10064 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
10069 if(TowardsLocation !=
"")
10071 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at " + DepTime;
10075 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
10080 if(TowardsLocation !=
"")
10082 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at " + DepTime;
10086 RetStr +=
"\nNew service departs at " + DepTime;
10247 ActiveTrackElementNameMapEntry.second = 0;
10253 std::ifstream TTBLFile(FileName, std::ios_base::binary);
10256 if(TTBLFile.is_open())
10258 char *TrainTimetableString =
new char[10000];
10260 bool EndOfFile =
false;
10263 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
10265 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
10272 delete[] TrainTimetableString;
10276 AnsiString OneLine(TrainTimetableString);
10277 bool FinalCallFalse =
false;
10278 while((Count == 0) && !
ProcessOneTimetableLine(5, Count, OneLine, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
10282 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
10283 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
10288 TimetableMessage(GiveMessages,
"Timetable invalid - unable to find a valid start time on its own line");
10290 delete[] TrainTimetableString;
10294 OneLine = AnsiString(TrainTimetableString);
10300 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
10302 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
10312 OneLine = AnsiString(TrainTimetableString);
10314 if(OneLine.Length() > 9999)
10316 TimetableMessage(GiveMessages,
"Timetable contains a line that is too long - 10,000 or more characters!");
10318 delete[] TrainTimetableString;
10322 bool FinalCallFalse =
false;
10323 if(!
ProcessOneTimetableLine(6, Count, OneLine, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
10327 delete[] TrainTimetableString;
10331 if(EndOfFile && (Count < 2))
10334 TimetableMessage(GiveMessages,
"Timetable has too few or no relevant entries - must have a start time on its own line and at least one train");
10336 delete[] TrainTimetableString;
10342 delete[] TrainTimetableString;
10347 TimetableMessage(GiveMessages,
"Failed to open timetable file, make sure it's spelled correctly, it exists and isn't open in another application");
10358 bool CheckLocationsExistInRailway)
10483 AnsiString((
short)FinalCall) +
"," + AnsiString((
short)CheckLocationsExistInRailway));
10493 if(OneLine[1] !=
'*')
10495 int SCPos = OneLine.Pos(
';');
10506 bool AllCommas =
true;
10508 for(
int x = 1; x < OneLine.Length() + 1; x++)
10510 if(OneLine[x] !=
',')
10515 if(AllCommas || (OneLine ==
""))
10530 AnsiString First =
"", Second =
"", Third =
"", Fourth =
"";
10531 int RearStartOrRepeatMins = 0, FrontStartOrRepeatDigits = 0, NumberOfRepeats = 0;
10532 TDateTime EventTime(0), ArrivalTime(0), DepartureTime(0);
10533 TDateTime StartTime(0);
10535 bool Warning =
false;
10562 AnsiString TrainInfoStr =
"", HeadCode =
"", Description =
"";
10563 int StartSpeed = 0, MaxRunningSpeed = 0, Mass = 0;
10564 double MaxBrakeRate = 0;
10565 double PowerAtRail = 0;
10566 int SignallerSpeed = 0;
10567 if(OneLine[1] ==
'*')
10573 int Pos = OneLine.Pos(
',');
10576 int SubStringLength = 20;
10577 if(OneLine.Length() < 20)
10579 SubStringLength = OneLine.Length();
10581 TimetableMessage(GiveMessages,
"Error in timetable - entry incomplete: see '" + OneLine.SubString(1, SubStringLength) +
"'....");
10585 TrainInfoStr = OneLine.SubString(1, Pos - 1);
10586 if(!
SplitTrainInfo(0, TrainInfoStr, HeadCode, Description, StartSpeed, MaxRunningSpeed, Mass, MaxBrakeRate, PowerAtRail, SignallerSpeed,
10596 TempTrainDataEntry.
HeadCode = HeadCode;
10600 TempTrainDataEntry.
Mass = Mass;
10608 AnsiString NewRemainder = OneLine.SubString(Pos + 1, OneLine.Length() - Pos);
10611 while(NewRemainder[NewRemainder.Length()] ==
',')
10613 if(NewRemainder.Length() > 1)
10615 NewRemainder = NewRemainder.SubString(1, NewRemainder.Length() - 1);
10624 if(NewRemainder ==
"")
10626 TimetableMessage(GiveMessages,
"Error in timetable - no events following train: '" + OneLine +
"'");
10631 int CommaCount = 0;
10632 for(
int x = 1; x < NewRemainder.Length() + 1; x++)
10634 if(NewRemainder[x] ==
',')
10639 if(CommaCount == 0)
10641 if((NewRemainder.SubString(7, 3) !=
"Snt") || (NewRemainder[NewRemainder.Length()] !=
'S'))
10643 int SubStringLength = 20;
10644 if(OneLine.Length() < 20)
10646 SubStringLength = OneLine.Length();
10649 "Error in timetable - must have at least a start and a finish event for a train that is not started under signaller control - see line beginning: '" +
10650 OneLine.SubString(1, SubStringLength) +
"'....");
10655 AnsiString OneEntry =
"";
10660 bool FinishFlag =
false;
10661 for(
int x = 0; x < CommaCount + 1; x++)
10663 if((CommaCount == 0) || (x < CommaCount))
10668 if(CommaCount == 0)
10670 OneEntry = NewRemainder;
10675 Pos = NewRemainder.Pos(
',');
10676 OneEntry = NewRemainder.SubString(1, Pos - 1);
10677 NewRemainder = NewRemainder.SubString(Pos + 1, NewRemainder.Length() - Pos);
10683 RearStartOrRepeatMins = 0;
10684 FrontStartOrRepeatDigits = 0;
10685 NumberOfRepeats = 0;
10686 if(!
SplitEntry(0, OneEntry, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
10687 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
10689 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneEntry +
"'");
10694 if(Warning && (Second ==
"Frh"))
10696 TimetableMessage(GiveMessages,
"Error in line - '" + OneEntry +
"': warnings cannot be given for 'Frh' events");
10700 if(Warning && (Second ==
"Fjo"))
10703 "': warnings cannot be given for 'Fjo' events, for a train join warning add a 'W' prefix to the 'jbo' event");
10709 if(SequenceType !=
Start)
10711 TimetableMessage(GiveMessages,
"Error in timetable - First event not a start event: '" + OneEntry +
"'");
10715 if((Second ==
"Snt") && (Fourth ==
'S') && (NewRemainder !=
""))
10717 if(NewRemainder[1] !=
'R')
10720 "Error in timetable - the only event that can follow a train created under signaller control is a repeat, see '" +
10726 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
10730 if((HeadCode ==
"") || (Description ==
"") || (MaxRunningSpeed == 0) || (Mass == 0) || (MaxBrakeRate == 0))
10733 TimetableMessage(GiveMessages,
"Error in timetable - train information incomplete before 'Snt' or 'Snt-sh' start event: '" +
10739 if((Second ==
"Sfs") || (Second ==
"Sns") || (Second ==
"Sns-sh") || (Second ==
"Sns-fsh"))
10744 TimetableMessage(GiveMessages,
"Error in timetable - headcode missing before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
10749 if((StartSpeed != 0) || (MaxRunningSpeed != 0) || (Mass != 0) || (MaxBrakeRate != 0) || (PowerAtRail != 0))
10752 "Error in timetable - information additional to a headcode & optional description given before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
10759 if(SequenceType ==
Finish)
10768 TDateTime TempTime;
10774 ActionVectorEntry.
Warning = Warning;
10790 ActionVectorEntry.
Command = Second;
10805 else if(FormatType ==
TimeCmd)
10811 ActionVectorEntry.
Command = Second;
10819 ActionVectorEntry.
Command = Second;
10820 ActionVectorEntry.
ExitList = ExitList;
10828 ActionVectorEntry.
Command = Second;
10842 ActionVectorEntry.
Command = Second;
10853 ActionVectorEntry.
Command = Second;
10863 ActionVectorEntry.
Command = Second;
10872 ActionVectorEntry.
Command = Second;
10881 ActionVectorEntry.
Command = Second;
10887 ActionVectorEntry.
Command = Second;
10889 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
10894 OneEntry = NewRemainder;
10899 RearStartOrRepeatMins = 0;
10900 FrontStartOrRepeatDigits = 0;
10901 NumberOfRepeats = 0;
10902 if((FinishFlag) && (OneEntry[1] !=
'R'))
10905 TimetableMessage(GiveMessages,
"Error in timetable - Last event = '" + OneEntry +
"'. An earlier finish event has been found with something other than a repeat following it - only a repeat can follow a finish event.");
10909 if(OneEntry[1] !=
'R')
10911 if(!
SplitEntry(1, OneEntry, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
10912 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
10914 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneEntry +
"'");
10918 if(SequenceType !=
Finish)
10920 TimetableMessage(GiveMessages,
"Error in timetable - last event should be a finish: '" + OneEntry +
"'");
10927 TDateTime TempTime;
10933 ActionVectorEntry.
Warning = Warning;
10940 ActionVectorEntry.
Command = Second;
10948 ActionVectorEntry.
Command = Second;
10957 ActionVectorEntry.
Command = Second;
10966 ActionVectorEntry.
Command = Second;
10976 ActionVectorEntry.
Command = Second;
10977 ActionVectorEntry.
ExitList = ExitList;
10981 ActionVectorEntry.
Command = Second;
10983 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
10988 if(!
SplitRepeat(0, OneEntry, RearStartOrRepeatMins, FrontStartOrRepeatDigits, NumberOfRepeats, GiveMessages))
11004 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
11023 if((HeadCode[HeadCode.Length() - 1] <
'0') || (HeadCode[HeadCode.Length() - 1] >
'9'))
11028 if((HeadCode[HeadCode.Length()] <
'0') || (HeadCode[HeadCode.Length()] >
'9'))
11043 if(TimeStr.Length() < 5)
11048 if((TimeStr[1] <
'0') || (TimeStr[1] >
'9'))
11053 if((TimeStr[2] <
'0') || (TimeStr[2] >
'9'))
11058 if(TimeStr[3] !=
':')
11063 if((TimeStr[4] <
'0') || (TimeStr[4] >
'5'))
11068 if((TimeStr[5] <
'0') || (TimeStr[5] >
'9'))
11073 while(TimeStr.Length() > 5)
11075 TimeStr = TimeStr.SubString(1, TimeStr.Length() - 1);
11077 double WholeHours = (AnsiString(TimeStr[1]) + AnsiString(TimeStr[2])).ToDouble();
11078 double FracHour = ((AnsiString(TimeStr[4]) + AnsiString(TimeStr[5])).ToDouble()) / 60.0;
11080 if((WholeHours + FracHour) >= 95.98334)
11085 Time = TDateTime((WholeHours + FracHour) / 24);
11092 bool TTrainController::SplitEntry(
int Caller, AnsiString OneEntry,
bool GiveMessages,
bool CheckLocationsExistInRailway, AnsiString &First, AnsiString &Second,
11093 AnsiString &Third, AnsiString &Fourth,
int &RearStartOrRepeatMins,
int &FrontStartOrRepeatDigits,
TTimetableFormatType &FormatType,
11102 TDateTime TempTime;
11104 if(OneEntry.Length() > 0)
11106 if(OneEntry[1] ==
'W')
11109 OneEntry = OneEntry.SubString(2, OneEntry.Length() - 1);
11113 if(OneEntry ==
"Frh")
11123 if(OneEntry.Length() < 7)
11128 int Pos = OneEntry.Pos(
';');
11136 First = OneEntry.SubString(1, 5);
11142 AnsiString Remainder = OneEntry.SubString(Pos + 1, OneEntry.Length() - Pos);
11144 if((Remainder[1] >=
'0') && (Remainder[1] <=
'9'))
11147 if(Remainder.Length() < 7)
11152 Pos = Remainder.Pos(
';');
11159 Second = Remainder.SubString(1, 5);
11165 Third = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11178 Pos = Remainder.Pos(
';');
11181 Second = Remainder;
11182 if(Second ==
"cdt")
11207 if((Pos != 4) && (Pos != 7) && (Pos != 8))
11213 Second = Remainder.SubString(1, Pos - 1);
11215 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11217 Pos = Remainder.Pos(
';');
11224 Third = Remainder.SubString(1, Pos - 1);
11225 Fourth = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11227 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
11230 int SpacePos = Third.Pos(
' ');
11236 AnsiString RearStartStr = Third.SubString(1, SpacePos - 1);
11237 AnsiString FrontStartStr = Third.SubString(SpacePos + 1, Third.Length() - SpacePos);
11239 if(CheckLocationsExistInRailway)
11249 if(Second ==
"Snt")
11252 SequenceType =
Start;
11261 SequenceType =
Start;
11272 if(Second ==
"Sns-sh")
11276 SequenceType =
Start;
11291 if(Second ==
"F-nshs")
11305 if(Second ==
"Sns-fsh")
11309 SequenceType =
Start;
11319 if(Second ==
"Fns-sh")
11339 if(Second ==
"pas")
11354 if(Second ==
"Fer")
11361 if(CheckLocationsExistInRailway)
11373 if((Second !=
"Fns") && (Second !=
"Fjo") && (Second !=
"jbo") && (Second !=
"fsp") && (Second !=
"rsp") && (Second !=
"Sfs") && (Second !=
"Sns") &&
11374 (Second !=
"Frh-sh"))
11386 if(Second ==
"Frh-sh")
11394 if((Second ==
"Fns") || (Second ==
"Fjo") || (Second ==
"Frh-sh"))
11398 if((Second ==
"jbo") || (Second ==
"fsp") || (Second ==
"rsp"))
11402 if((Second ==
"Sfs") || (Second ==
"Sns"))
11404 SequenceType =
Start;
11422 if((LocStr[1] >=
'0') && (LocStr[1] <=
'9'))
11427 for(
int x = 1; x < LocStr.Length() + 1; x++)
11429 if(LocStr[x] <
' ')
11434 if(LocStr[x] >
'z')
11441 if(CheckLocationsExistInRailway)
11446 "' appears in the timetable but is not a valid name. To be valid the name must be a stopping location and apply to one or more platforms " +
11447 "(not concourses on their own), or to track at a blue non-station named location. BUT NOTE THAT trains can't stop at continuations so a name " +
11448 "that includes a continuation will not be valid.");
11466 if((HeadCode.Length() < 4) || (HeadCode.Length() > 8))
11469 "', length must be between 4 and 8 characters, and last 4 must be a legitimate headcode. This error can also be caused by omitting a service reference after Sns, Snt-sh, Sns-sh, Fns, Fns-sh or Frh-sh");
11474 for(
int x = 1; x < (HeadCode.Length() + 1); x++)
11476 if((HeadCode[x] <
' ') || (HeadCode[x] >
'~'))
11478 TimetableMessage(GiveMessages,
"Non-printable character in headcode '" + HeadCode +
"'");
11484 for(
int x = 3; x >= 0; x--)
11486 if(((HeadCode[HeadCode.Length() - x] <
'A') || (HeadCode[HeadCode.Length() - x] >
'Z')) && ((HeadCode[HeadCode.Length() - x] <
'a') ||
11487 (HeadCode[HeadCode.Length() - x] >
'z')) && ((HeadCode[HeadCode.Length() - x] <
'0') || (HeadCode[HeadCode.Length() - x] >
'9')))
11489 TimetableMessage(GiveMessages,
"Headcode error in '" + HeadCode +
"', headcode must consist of letters and digits only");
11505 AnsiString CurrentID =
"";
11507 if(IDSet.Length() == 0)
11509 TimetableMessage(GiveMessages,
"Must have at least one exit element ID following 'Fer'");
11513 for(
int x = 1; x <= IDSet.Length(); x++)
11516 if(((C <
'0') || (C >
'9')) && (C !=
' ') && (C !=
'N') && (C !=
'-'))
11518 TimetableMessage(GiveMessages,
"Illegal character in the set of element IDs following 'Fer' in '" + IDSet +
"'");
11523 int Pos = IDSet.Pos(
' ');
11534 CurrentID = IDSet.SubString(1, Pos - 1);
11535 IDSet = IDSet.SubString(Pos + 1, IDSet.Length() - Pos);
11547 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' is not an exit");
11554 if(!ExitList.empty())
11556 for(
TNumListIterator ELIT = ExitList.begin(); ELIT != ExitList.end(); ELIT++)
11558 if(*ELIT == VecPos)
11560 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' duplicates an earlier element");
11567 ExitList.push_back(VecPos);
11577 Pos = IDSet.Pos(
' ');
11584 int &Mass,
double &MaxBrakeRate,
double &PowerAtRail,
int &SignallerSpeed,
bool GiveMessages)
11591 AnsiString Remainder =
"";
11592 int SemiColonCount = 0;
11594 for(
int x = 1; x < TrainInfoStr.Length() + 1; x++)
11596 if(TrainInfoStr[x] ==
';')
11601 if((SemiColonCount != 6) && (SemiColonCount != 7) && (SemiColonCount != 1) && (SemiColonCount != 0))
11603 TimetableMessage(GiveMessages,
"Error in train information in '" + TrainInfoStr +
11604 "'. Should be headcode + optional description for a continuing service;" +
11605 " or headcode, description, start speed, max running speed, mass, brake force, power (and optional signaller max. speed) for a new service");
11609 if(SemiColonCount == 0)
11611 HeadCode = TrainInfoStr;
11620 if(SemiColonCount == 1)
11622 Pos = TrainInfoStr.Pos(
';');
11623 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
11624 Description = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
11630 if(Description ==
"")
11632 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
11636 if(Description.Length() > 60)
11638 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
11642 for(
int x = 1; x < Description.Length() + 1; x++)
11644 if((Description[x] <
' ') || (Description[x] >
'~'))
11646 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
11655 Pos = TrainInfoStr.Pos(
';');
11656 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
11657 Remainder = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
11663 Pos = Remainder.Pos(
';');
11664 Description = Remainder.SubString(1, Pos - 1);
11665 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11666 if(Description ==
"")
11668 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
11672 if(Description.Length() > 60)
11674 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
11678 for(
int x = 1; x < Description.Length() + 1; x++)
11680 if((Description[x] <
' ') || (Description[x] > 126))
11682 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
11687 Pos = Remainder.Pos(
';');
11688 AnsiString StartSpeedStr = Remainder.SubString(1, Pos - 1);
11690 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11691 if(StartSpeedStr ==
"")
11693 TimetableMessage(GiveMessages,
"Train starting speed missing in '" + TrainInfoStr +
"'");
11697 for(
int x = 1; x < StartSpeedStr.Length() + 1; x++)
11699 if((StartSpeedStr[x] <
'0') || (StartSpeedStr[x] >
'9'))
11701 TimetableMessage(GiveMessages,
"Train start speed contains invalid characters in '" + TrainInfoStr +
"'");
11706 StartSpeed = StartSpeedStr.ToInt();
11712 TimetableMessage(GiveMessages,
"Train starting speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
11716 Pos = Remainder.Pos(
';');
11717 AnsiString MaxRunningSpeedStr = Remainder.SubString(1, Pos - 1);
11719 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11720 if(MaxRunningSpeedStr ==
"")
11722 TimetableMessage(GiveMessages,
"Train maximum running speed missing in '" + TrainInfoStr +
"'");
11726 for(
int x = 1; x < MaxRunningSpeedStr.Length() + 1; x++)
11728 if((MaxRunningSpeedStr[x] <
'0') || (MaxRunningSpeedStr[x] >
'9'))
11730 TimetableMessage(GiveMessages,
"Train maximum running speed contains invalid characters in '" + TrainInfoStr +
"'");
11735 MaxRunningSpeed = MaxRunningSpeedStr.ToInt();
11741 TimetableMessage(GiveMessages,
"Train maximum running speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
11745 if(MaxRunningSpeed < 10)
11748 MaxRunningSpeed = 10;
11751 TimetableMessage(GiveMessages,
"Train maximum running speed can't be less than 10km/h in '" + TrainInfoStr +
"', it will be set to 10km/h");
11755 Pos = Remainder.Pos(
';');
11756 AnsiString MassStr = Remainder.SubString(1, Pos - 1);
11758 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11761 TimetableMessage(GiveMessages,
"Train mass missing in '" + TrainInfoStr +
"'");
11765 for(
int x = 1; x < MassStr.Length() + 1; x++)
11767 if((MassStr[x] <
'0') || (MassStr[x] >
'9'))
11769 TimetableMessage(GiveMessages,
"Train mass contains invalid characters in '" + TrainInfoStr +
"'");
11774 Mass = MassStr.ToInt() * 1000;
11780 TimetableMessage(GiveMessages,
"Train mass > 10,000 tonnes in '" + TrainInfoStr +
"'. Setting it to 10,000 tonnes");
11786 TimetableMessage(GiveMessages,
"Train mass zero in '" + TrainInfoStr +
"'");
11790 Pos = Remainder.Pos(
';');
11791 AnsiString MaxBrakeForceStr = Remainder.SubString(1, Pos - 1);
11793 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11794 if(MaxBrakeForceStr ==
"")
11796 TimetableMessage(GiveMessages,
"Train braking force missing in '" + TrainInfoStr +
"'");
11800 for(
int x = 1; x < (MaxBrakeForceStr.Length() + 1); x++)
11802 if((MaxBrakeForceStr[x] !=
'.') && ((MaxBrakeForceStr[x] <
'0') || (MaxBrakeForceStr[x] >
'9')))
11804 TimetableMessage(GiveMessages,
"Train braking force contains invalid characters in '" + TrainInfoStr +
"'");
11809 double MaxBrakeForce = MaxBrakeForceStr.ToDouble() * 1000;
11812 if((MaxBrakeForce / Mass) > 1)
11814 MaxBrakeForce = Mass;
11817 TimetableMessage(GiveMessages,
"Train braking force too high in '" + TrainInfoStr +
"'. Setting it to the same as the train mass");
11821 if((MaxBrakeForce / Mass) < 0.01)
11823 MaxBrakeForce = Mass * 0.01;
11826 TimetableMessage(GiveMessages,
"Train braking force too low in '" + TrainInfoStr +
"'. Setting it to 1% of the train mass");
11831 MaxBrakeRate = MaxBrakeForce / Mass * 9.81;
11833 AnsiString GrossPowerStr =
"", SignallerSpeedStr =
"";
11835 if(SemiColonCount == 6)
11837 GrossPowerStr = Remainder;
11838 SignallerSpeedStr =
"30";
11842 Pos = Remainder.Pos(
';');
11843 GrossPowerStr = Remainder.SubString(1, Pos - 1);
11844 SignallerSpeedStr = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11847 if(GrossPowerStr ==
"")
11849 TimetableMessage(GiveMessages,
"Train power missing in '" + TrainInfoStr +
"'");
11853 for(
int x = 1; x < GrossPowerStr.Length() + 1; x++)
11855 if((GrossPowerStr[x] <
'0') || (GrossPowerStr[x] >
'9'))
11857 TimetableMessage(GiveMessages,
"Train power contains invalid characters in '" + TrainInfoStr +
"'");
11863 double GrossPower = GrossPowerStr.ToInt() * 1000;
11870 TimetableMessage(GiveMessages,
"Train power > 100,000kW in '" + TrainInfoStr +
"'. Setting it to 100,000kW");
11874 else if(GrossPower == 0)
11879 else if((GrossPower > 0) && (GrossPower < 10000))
11882 GrossPower = 10000;
11884 PowerAtRail = GrossPower * 0.8;
11888 if(SignallerSpeedStr ==
"")
11890 TimetableMessage(GiveMessages,
"Signaller speed not set in '" + TrainInfoStr +
"', either set a value or remove the extra semicolon");
11894 for(
int x = 1; x < SignallerSpeedStr.Length() + 1; x++)
11896 if((SignallerSpeedStr[x] <
'0') || (SignallerSpeedStr[x] >
'9'))
11898 TimetableMessage(GiveMessages,
"Signaller speed contains invalid characters in '" + TrainInfoStr +
"'");
11903 SignallerSpeed = SignallerSpeedStr.ToInt();
11909 TimetableMessage(GiveMessages,
"Signaller speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
11913 if(SignallerSpeed < 10)
11916 SignallerSpeed = 10;
11919 TimetableMessage(GiveMessages,
"Signaller speed can't be less than 10km/h in '" + TrainInfoStr +
"', it will be set to 10km/h");
11937 if(OneEntry.Length() < 7)
11939 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
11943 int SemiColonCount = 0;
11945 for(
int x = 1; x < OneEntry.Length() + 1; x++)
11947 if(OneEntry[x] ==
';')
11952 if(SemiColonCount != 3)
11954 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
11958 if((OneEntry[1] !=
'R') || (OneEntry[2] !=
';'))
11960 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
11964 AnsiString Remainder = OneEntry.SubString(3, OneEntry.Length() - 2);
11969 Pos = Remainder.Pos(
';');
11970 AnsiString MinutesStr = Remainder.SubString(1, Pos - 1);
11972 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11973 if(MinutesStr ==
"")
11975 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute increment segment missing");
11979 if(MinutesStr.Length() > 3)
11982 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute value too high, maximum value is 999");
11986 for(
int x = 1; x < MinutesStr.Length() + 1; x++)
11988 if((MinutesStr[x] <
'0') || (MinutesStr[x] >
'9'))
11990 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in minute increment segment");
11995 RearStartOrRepeatMins = MinutesStr.ToInt();
11996 if(RearStartOrRepeatMins == 0)
11998 TimetableMessage(GiveMessages,
"Repeat minute increment is zero in: '" + OneEntry +
"' - can't have a zero value");
12002 Pos = Remainder.Pos(
';');
12003 AnsiString DigitsStr = Remainder.SubString(1, Pos - 1);
12005 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12006 if(DigitsStr ==
"")
12008 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - headcode increment segment missing");
12012 for(
int x = 1; x < DigitsStr.Length() + 1; x++)
12014 if((DigitsStr[x] <
'0') || (DigitsStr[x] >
'9'))
12016 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in headcode increment segment");
12021 if(DigitsStr.Length() > 2)
12023 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - maximum number of digits for headcode increment is 2");
12027 FrontStartOrRepeatDigits = DigitsStr.ToInt();
12041 "' - a repeating service with incrementing digits must have digits as its last two headcode characters");
12045 AnsiString NumberStr = Remainder;
12047 if(NumberStr ==
"")
12049 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - number of repeats missing");
12053 if(NumberStr.Length() > 4)
12056 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - repeat value too high, no timetabled event can exceed 95 hours & 59 minutes");
12060 for(
int x = 1; x < NumberStr.Length() + 1; x++)
12062 if((NumberStr[x] <
'0') || (NumberStr[x] >
'9'))
12065 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in number of repeats");
12070 NumberOfRepeats = NumberStr.ToInt();
12071 if(NumberOfRepeats == 0)
12073 TimetableMessage(GiveMessages,
"Number of repeats is zero in: '" + OneEntry +
"' - if no repeats are needed the repeat should be omitted");
12245 SecondPassMessage(GiveMessages,
"Error in timetable - there appear to be no train services in the timetable, it must contain at least one");
12264 TwoLocationFlag =
false;
12270 SecondPassMessage(GiveMessages,
"Error in timetable - the following service has no listed events, there must be at least one: " + TDEntry.
HeadCode);
12284 SecondPassMessage(GiveMessages,
"Error in timetable - service must have a start event and at least one other for: " + TDEntry.
HeadCode);
12300 "Error in timetable - a signaller control service can have no more than one item (a repeat) after the start event, see: " +
12312 "Error in timetable - a signaller control service cannot have any other than a repeat after the start event, see: " + TDEntry.
HeadCode);
12339 SecondPassMessage(GiveMessages,
"Error in timetable - finish events Fns-sh and Frh-sh not permitted immediately after an Snt entry for: " +
12350 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12355 SecondPassMessage(GiveMessages,
"Error in timetable - a start event is present that is not the first event for: " + TDEntry.
HeadCode);
12365 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12370 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat is present that is not the last item for: " + TDEntry.
HeadCode);
12380 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12391 SecondPassMessage(GiveMessages,
"Error in timetable - the last item must be either a finish event or a repeat for: " + TDEntry.
HeadCode);
12401 SecondPassMessage(GiveMessages,
"Error in timetable - the last event before the repeat must be a finish for: " + TDEntry.
HeadCode);
12413 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12420 SecondPassMessage(GiveMessages,
"Error in timetable - a finish event must be either the last or last but one for: " + TDEntry.
HeadCode);
12429 SecondPassMessage(GiveMessages,
"Error in timetable - the only event that can follow a finish event is a repeat for: " +
12449 if((AVEntry0.
Command ==
"Snt") || (AVEntry0.
Command ==
"Snt-sh"))
12451 AnsiString LocationName =
"";
12467 SecondPassMessage(GiveMessages,
"Error in timetable - stopped 'Snt' or 'Snt-sh' followed by an illegal event for: " +
12468 TDEntry.
HeadCode +
". The event isn't valid for a stationary train.");
12477 SecondPassMessage(GiveMessages,
"Error in timetable - 'Snt' or 'Snt-sh' event at stop location but start speed not zero for: " +
12486 if(AVEntry0.
Command ==
"Snt-sh")
12500 SecondPassMessage(GiveMessages,
"Error in timetable - unlocated 'Snt' not followed by 'Fer', 'pas' or an arrival for: " +
12516 SecondPassMessage(GiveMessages,
"Error in timetable - 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' followed by an illegal event for: " +
12517 TDEntry.
HeadCode +
". The event isn't valid for a stationary train.");
12528 bool FoundFlag =
false;
12534 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12546 SecondPassMessage(GiveMessages,
"Error in timetable - no location departure following an 'Sfs', 'Sns', 'Sns-sh'or 'Sns-fsh' event for: " +
12559 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12568 ": an event should have had a location name associated with it but it could not be found");
12574 for(
unsigned int z = y + 1; z <
TrainDataVector.at(x).ActionVector.size(); z++)
12596 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12606 SecondPassMessage(GiveMessages,
"Error in timetable - only a repeat can follow a finish entry for: " + TDEntry.
HeadCode);
12613 if(AVEntry.
Command ==
"F-nshs")
12618 SecondPassMessage(GiveMessages,
"Error in timetable - F-nshs (shuttle link) must be the last event for: " + TDEntry.
HeadCode);
12646 SecondPassMessage(GiveMessages,
"Error in timetable - a jbo event is followed by an illegal event for: " + TDEntry.
HeadCode +
12647 ". The event isn't valid for a stationary train.");
12657 SecondPassMessage(GiveMessages,
"Error in timetable - a train split can't be the last event for: " + TDEntry.
HeadCode);
12665 SecondPassMessage(GiveMessages,
"Error in timetable - a train split is followed by an illegal event for: " + TDEntry.
HeadCode +
12666 ". The event isn't valid for a stationary train.");
12684 SecondPassMessage(GiveMessages,
"Error in timetable - a 'cdt' is followed by an illegal event for: " + TDEntry.
HeadCode +
12685 ". The event isn't valid for a stationary train.");
12695 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure can't be the last event for: " + TDEntry.
HeadCode);
12703 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure is followed by an illegal event for: " +
12704 TDEntry.
HeadCode +
". The event isn't valid for a moving train.");
12722 SecondPassMessage(GiveMessages,
"Error in timetable - a pass time is followed by an illegal event for: " + TDEntry.
HeadCode +
12723 ". The event isn't valid for a moving train.");
12745 bool LastEntryIsAnArrival =
false;
12752 LastEntryIsAnArrival =
false;
12753 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12760 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
12762 if(LastEntryIsAnArrival)
12766 LastEntryIsAnArrival =
false;
12772 LastEntryIsAnArrival =
true;
12779 LastEntryIsAnArrival =
true;
12780 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12787 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
12789 if(LastEntryIsAnArrival)
12793 LastEntryIsAnArrival =
false;
12799 LastEntryIsAnArrival =
true;
12809 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12817 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival can't be the last event for: " + TDEntry.
HeadCode);
12825 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival is followed by an illegal event for: " + TDEntry.
HeadCode +
12826 ". The event isn't valid for a stationary train.");
12837 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure can't be the last event for: " + TDEntry.
HeadCode);
12845 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure is followed by an illegal event for: " + TDEntry.
HeadCode +
12846 ". The event isn't valid for a moving train.");
12860 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12867 throw Exception(
"Timetable error, TimeLoc entry has EventTime not -1 for " + TDEntry.
HeadCode);
12871 throw Exception(
"Timetable error, TimeLoc entry has neither arrival nor departure time set for " + TDEntry.
HeadCode);
12878 throw Exception(
"Timetable error, TimeTimeLoc entry has EventTime not -1 for " + TDEntry.
HeadCode);
12882 throw Exception(
"Timetable error, TimeTimeLoc entry has either arrival or departure time not set for " + TDEntry.
HeadCode);
12891 throw Exception(
"Timetable error, Cmd or PassTime entry has EventTime not set for " + TDEntry.
HeadCode);
12895 throw Exception(
"Timetable error, Cmd or PassTime entry has either arrival or departure time set for " + TDEntry.
HeadCode);
12902 throw Exception(
"Timetable error, Repeat entry has a time set for " + TDEntry.
HeadCode);
12913 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12928 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure has a later arrival than departure time for: " +
12936 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure has too early an arrival time for: " +
12951 SecondPassMessage(GiveMessages,
"Error in timetable - a timed location event has a time that is too early for: " + TDEntry.
HeadCode);
12963 SecondPassMessage(GiveMessages,
"Error in timetable - a timed location event has a time that is too early for: " + TDEntry.
HeadCode);
12975 SecondPassMessage(GiveMessages,
"Error in timetable - a train event has a time that is set too early for: " + TDEntry.
HeadCode +
12976 ", may be before timetable start time");
12987 AnsiString LastLocationName =
"";
12991 bool LastEntryIsAnArrival =
false;
12996 LastEntryIsAnArrival =
false;
12997 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
12998 if(LastLocationName !=
"")
13000 throw Exception(
"Timetable error, moving Snt entry has LocationName set for " + TDEntry.
HeadCode);
13002 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size();
13015 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
13027 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
13040 TwoLocationFlag =
true;
13045 LastEntryIsAnArrival =
false;
13049 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
13052 "Error in timetable - a location event for a timed departure is different from the arrival location for: " + TDEntry.
HeadCode);
13057 else if(!LastEntryIsAnArrival && (AVEntry.
LocationName == LastLocationName))
13060 "Error in timetable - a location event for a timed arrival is the same as the earlier departure location for: " + TDEntry.
HeadCode);
13066 LastEntryIsAnArrival = !LastEntryIsAnArrival;
13072 LastEntryIsAnArrival =
true;
13073 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
13074 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13086 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
13098 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
13111 TwoLocationFlag =
true;
13116 LastEntryIsAnArrival =
false;
13120 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
13123 "Error in timetable - a location event for a timed departure is different from the arrival location for: " + TDEntry.
HeadCode);
13131 "A location event for a timed arrival is the same as the earlier departure location for: " + TDEntry.
HeadCode +
". Please correct if this is an error.\n\nThis warning will not be shown again.");
13138 LastEntryIsAnArrival = !LastEntryIsAnArrival;
13146 AnsiString LocationNameToBeChecked =
"";
13151 unsigned int y = 0;
13165 LocationNameToBeChecked = TDEntry.
ActionVector.at(y).LocationName;
13166 for(
unsigned int z = y; z < TDEntry.
ActionVector.size(); z++)
13184 for(
unsigned int a = z; a < TDEntry.
ActionVector.size(); a++)
13193 TwoLocationFlag =
true;
13204 if(TwoLocationFlag)
13214 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13219 throw Exception(
"Error, non- 'Snt', 'Fer' or Repeat entry doesn't have a location name set for " + TDEntry.
HeadCode);
13221 AnsiString LocName =
"";
13227 throw Exception(
"Error, 'Snt' entry at a stop location doesn't have a location name set for " + TDEntry.
HeadCode);
13234 throw Exception(
"Error, 'Snt' unlocated entry has a location name set for " + TDEntry.
HeadCode);
13257 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13282 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13304 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13326 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13345 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13348 if((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh"))
13363 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13368 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has FormatType unset for: " + TDEntry.
HeadCode);
13372 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has SequenceType unset for: " + TDEntry.
HeadCode);
13376 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has LocationType unset for: " + TDEntry.
HeadCode);
13380 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has ShuttleLinkType unset for: " + TDEntry.
HeadCode);
13419 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13421 AnsiString LocName =
TrainDataVector.at(x).ActionVector.at(y).LocationName;
13427 SecondPassMessage(GiveMessages,
"Error in timetable - continuation names (" + LocName +
") must not be included, see service " + HC);
13440 int IncMinutes = 0;
13450 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13456 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat time exceeds 95h 59m, see service " + HC);
13462 if((
double)
TrainDataVector.at(x).ActionVector.at(y).ArrivalTime > -1)
13467 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat entry time exceeds 95h 59m, see service " + HC);
13473 if((
double)
TrainDataVector.at(x).ActionVector.at(y).DepartureTime > -1)
13478 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat entry time exceeds 95h 59m, see service " + HC);
13491 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13517 (AVEntry.
Command ==
"Fns-sh") || (AVEntry.
Command ==
"F-nshs"));
13525 if(HeadCode.Length() > 4)
13527 HeadCode = HeadCode.SubString(HeadCode.Length() - 3, 4);
13538 int ForwardCount = 0;
13539 int ReverseCount = 0;
13541 if(MainHeadCode == SecondHeadCode)
13543 SecondPassMessage(GiveMessages,
"Error in timetable - Service " + MainHeadCode +
" has an event that references itself");
13552 if(TDEntry.
HeadCode == MainHeadCode)
13554 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13569 if(ForwardCount == 0)
13572 throw Exception(
"Error, ForwardCount == 0 in CheckForDuplicateCrossReferences after called with found values");
13574 if(ForwardCount > 2)
13577 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + SecondHeadCode +
" from a train whose headcode is " +
13578 MainHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
13587 if(TDEntry.
HeadCode == SecondHeadCode)
13589 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13604 if(ReverseCount == 0)
13606 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + SecondHeadCode);
13611 if(ReverseCount > 2)
13614 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + MainHeadCode +
" from a train whose headcode is " +
13615 SecondHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
13620 if(ForwardCount != ReverseCount)
13622 SecondPassMessage(GiveMessages,
"Error in timetable - " + MainHeadCode +
" has a different number of references to " + SecondHeadCode +
13623 " than the other way round");
13654 int ForwardCount = 0;
13655 int ReverseCount = 0;
13656 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
13665 if(TDEntry.
HeadCode == MainHeadCode)
13667 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13670 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
13675 ForwardEntryPtr = &AVEntry;
13677 ForwardTDVectorNumber = x;
13680 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") ||
13681 (AVEntry.
Command ==
"Frh-sh")))
13686 ForwardEntryPtr = &AVEntry;
13688 ForwardTDVectorNumber = x;
13694 if(ForwardCount == 0)
13697 throw Exception(
"Error, ForwardCount == 0 in CheckCrossReferencesAndSetData after called with found values");
13699 if(ForwardCount > 1)
13701 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + OtherHeadCode +
" from a train whose headcode is " +
13711 if(TDEntry.
HeadCode == OtherHeadCode)
13713 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13716 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
13722 ReverseEntryPtr = &AVEntry;
13723 ReverseTDVectorNumber = x;
13726 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") || (AVEntry.
Command ==
"Frh-sh")))
13732 ReverseEntryPtr = &AVEntry;
13733 ReverseTDVectorNumber = x;
13740 if(ReverseCount == 0)
13742 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + OtherHeadCode);
13747 if(ReverseCount > 1)
13749 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
13756 bool ForwardShuttleStart = ((ForwardEntryPtr->Command ==
"Sns-sh") || (ForwardEntryPtr->Command ==
"Snt-sh"));
13757 bool ForwardShuttleFinish = ((ForwardEntryPtr->Command ==
"Fns-sh") || (ForwardEntryPtr->Command ==
"Frh-sh"));
13758 bool ReverseShuttleStart = ((ReverseEntryPtr->
Command ==
"Sns-sh") || (ReverseEntryPtr->
Command ==
"Snt-sh"));
13759 bool ReverseShuttleFinish = ((ReverseEntryPtr->
Command ==
"Fns-sh") || (ReverseEntryPtr->
Command ==
"Frh-sh"));
13763 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat");
13770 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + OtherHeadCode +
" does not have a repeat");
13775 if(ForwardEntryPtr->LocationName ==
"")
13777 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
13778 ". One or other service does not have a location set");
13785 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
13786 ". One or other service does not have a location set");
13791 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
13793 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
13794 " is at a different location to the referencing train " + MainHeadCode);
13802 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
13804 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
13805 " has a different event time to the referencing train " + MainHeadCode);
13813 if(ForwardShuttleStart && ReverseShuttleFinish)
13818 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle service " + MainHeadCode +
13819 " first repeat restart time not consistent with finish service " + OtherHeadCode);
13825 if((ReverseEntryPtr->
Command ==
"Sfs") || (ReverseEntryPtr->
Command ==
"Sns"))
13828 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
13830 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' or 'Sns' event (" + OtherHeadCode +
13831 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
13837 if(ReverseEntryPtr->
Command ==
"Fjo")
13840 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
13842 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fjo' event (" + OtherHeadCode +
13843 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
13849 if(ReverseEntryPtr->
Command ==
"Fns")
13852 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
13854 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fns' event (" + OtherHeadCode +
13855 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
13861 if(ForwardEntryPtr->Command ==
"Sfs")
13863 if((ReverseEntryPtr->
Command !=
"fsp") && (ReverseEntryPtr->
Command !=
"rsp"))
13866 "Error in timetable - unable to find a corresponding split train event for the train that starts from a split whose headcode is " +
13873 if((ForwardEntryPtr->Command ==
"fsp") || (ForwardEntryPtr->Command ==
"rsp"))
13875 if(ReverseEntryPtr->
Command !=
"Sfs")
13877 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sfs' event for the train split whose headcode is " +
13887 SecondPassMessage(GiveMessages,
"Error in timetable - can't find timetabled location '" + ForwardEntryPtr->LocationName +
"' in railway - perhaps there are concourses without platforms?");
13894 SecondPassMessage(GiveMessages,
"Error in timetable - can't find any named location elements at '" + ForwardEntryPtr->LocationName +
"' - perhaps there are concourses without platforms?");
13901 SecondPassMessage(GiveMessages,
"Error in timetable - location too short to split a train at " + ForwardEntryPtr->LocationName);
13906 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
13917 if(ForwardEntryPtr->Command ==
"Sns")
13919 if(ReverseEntryPtr->
Command !=
"Fns")
13921 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fns' event for the 'Sns' train whose headcode is " +
13922 MainHeadCode +
" and is formed from a service with headcode " + OtherHeadCode);
13928 if(ForwardEntryPtr->Command ==
"Fns")
13930 if(ReverseEntryPtr->
Command !=
"Sns")
13932 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns' event for the train whose headcode is " + MainHeadCode +
13933 " and forms a new service with headcode " + OtherHeadCode);
13940 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
13951 if(ForwardEntryPtr->Command ==
"jbo")
13953 if(ReverseEntryPtr->
Command !=
"Fjo")
13955 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fjo' event for the train whose headcode is " + MainHeadCode +
13956 " and is joined by a train with headcode " + OtherHeadCode);
13962 if(ForwardEntryPtr->Command ==
"Fjo")
13964 if(ReverseEntryPtr->
Command !=
"jbo")
13966 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'jbo' event for the train whose headcode is " + MainHeadCode +
13967 " and joins a train with headcode " + OtherHeadCode);
13974 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
13984 if(ForwardShuttleStart)
13987 if(!ReverseShuttleFinish)
13990 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + MainHeadCode +
13991 " from train whose headcode is " + OtherHeadCode +
", has to be Fns-sh, Frh-sh");
13997 if(ReverseShuttleStart)
14000 if(!ForwardShuttleFinish)
14003 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + OtherHeadCode +
14004 " from train whose headcode is " + MainHeadCode +
", has to be Fns-sh, Frh-sh");
14011 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
14023 bool MainRepeat =
false, OtherRepeat =
false;
14033 OtherRepeat =
true;
14036 if((MainRepeat && !OtherRepeat) || (!MainRepeat && OtherRepeat))
14038 SecondPassMessage(GiveMessages,
"Error in timetable - only one repeat is provided for the train whose headcode is " + MainHeadCode +
14039 " and the associated train with headcode " + OtherHeadCode);
14044 if(MainRepeat && OtherRepeat)
14050 SecondPassMessage(GiveMessages,
"Error in timetable - repeat items don't correspond for the train whose headcode is " + MainHeadCode +
14051 " and the associated train with headcode " + OtherHeadCode);
14073 while(Input[1] ==
' ')
14075 if(Input.Length() > 1)
14077 Input = Input.SubString(2, Input.Length() - 1);
14091 while(Input[Input.Length()] ==
' ')
14093 if(Input.Length() > 1)
14095 Input = Input.SubString(1, Input.Length() - 1);
14105 AnsiString Output =
"";
14106 bool DelimiterFound =
false;
14108 for(
int x = 1; x < Input.Length() + 1; x++)
14112 if(Input[x] ==
' ')
14117 if((Input[x] !=
',') && (Input[x] !=
';'))
14119 DelimiterFound =
false;
14120 Output = Output + Input[x];
14124 DelimiterFound =
true;
14125 Output = Output + Input[x];
14137 DelimiterFound =
false;
14138 for(
int x = Input.Length(); x > 0; x--)
14142 if(Input[x] ==
' ')
14147 if((Input[x] !=
',') && (Input[x] !=
';'))
14149 DelimiterFound =
false;
14150 Output = AnsiString(Input[x]) + Output;
14154 DelimiterFound =
true;
14155 Output = AnsiString(Input[x]) + Output;
14180 if((AVEntry0.
Command !=
"Snt") && (AVEntry0.
Command !=
"Snt-sh"))
14182 throw Exception(
"Error, first entry not 'Snt' or 'Snt-sh' in IsSNTEntryLocated");
14194 LocationName = LocRear;
14198 LocationName = LocFront;
14200 if(LocationName ==
"")
14221 for(
unsigned int y = 0; y < TDEntry.
ActionVector.size(); y++)
14262 int RearPosition = 0, FrontPosition = 0, RearExitPos = 0;
14265 if(RearPosition < 0)
14272 if(FrontPosition < 0)
14283 for(
int x = 0; x < 4; x++)
14285 if(RearTrackElement.
Conn[x] == FrontPosition)
14300 TimetableMessage(GiveMessages,
"Front of train attempting to start on a continuation at: " + FrontElementStr);
14307 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + FrontElementStr);
14313 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + RearElementStr);
14318 if((RearType ==
Points) && (RearExitPos == 3))
14320 TimetableMessage(GiveMessages,
"Front of train attempting to start on element connected to diverging points at: " + RearElementStr);
14326 TimetableMessage(GiveMessages,
"Rear of train attempting to start on element connected to diverging points at: " + FrontElementStr);
14341 AnsiString(RearExitPos));
14352 int FrontPosition = RearTrackElement.
Conn[RearExitPos];
14354 int FrontEntryPos = RearTrackElement.
ConnLinkPos[RearExitPos];
14357 AnsiString RearName, FrontName;
14373 FrontName = FrontTrackElement.
ElementID;
14376 int LockedVectorNumber;
14546 "," + AnsiString(IncDigits));
14549 throw Exception(
"Error, last 2 characters not both digits and IncDigits > 0 in GetRepeatHeadCode");
14554 return(BaseHeadCode);
14556 int BaseDigits = BaseHeadCode.SubString(3, 2).ToInt();
14557 int NextRepeatDigits = BaseDigits + (IncDigits * RepeatNumber);
14559 while(NextRepeatDigits >= 100)
14561 NextRepeatDigits -= 100;
14563 AnsiString NextRepeatDigitsStr = AnsiString(NextRepeatDigits);
14565 if(NextRepeatDigitsStr.Length() < 2)
14567 NextRepeatDigitsStr = AnsiString(
'0') + NextRepeatDigitsStr;
14569 AnsiString NextRepeatHeadCode = BaseHeadCode.SubString(1, 2) + NextRepeatDigitsStr;
14572 return(NextRepeatHeadCode);
14580 AnsiString(RepeatNumber) +
"," + AnsiString(IncMinutes));
14581 TDateTime NextRepeatTime = BasicTime + TDateTime(((
double)(RepeatNumber * IncMinutes)) / 1440.0);
14583 return(NextRepeatTime);
14592 AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes));
14593 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
14594 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
14595 int RepeatSecs = RepeatMinutes * 60;
14597 if((ForwardSecs > (ReverseSecs - RepeatSecs + 10)) || (ForwardSecs < (ReverseSecs - RepeatSecs - 10)))
14632 NonRepeatingHeadCode);
14633 int ForwardCount = 0;
14634 int ReverseCount = 0;
14635 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
14645 if(TDEntry.
HeadCode == MainHeadCode)
14647 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14653 ForwardEntryPtr = &AVEntry;
14655 ForwardTDVectorNumber = x;
14660 if(ForwardCount == 0)
14663 throw Exception(
"Error, ForwardCount == 0 in CheckNonRepeatingShuttleLinksAndSetData after called with found values");
14665 if(ForwardCount > 1)
14667 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + NonRepeatingHeadCode +
" from a train whose headcode is " +
14677 if(TDEntry.
HeadCode == NonRepeatingHeadCode)
14679 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14686 ReverseEntryPtr = &AVEntry;
14687 ReverseTDVectorNumber = x;
14693 if(ReverseCount == 0)
14695 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + NonRepeatingHeadCode);
14700 if(ReverseCount > 1)
14702 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
14703 NonRepeatingHeadCode);
14708 if(((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh")) && (MainTrainDataPtr->
ActionVector.back().FormatType ==
Repeat))
14710 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle connecting train " + MainHeadCode +
" shouldn't have a repeat");
14715 if((ForwardEntryPtr->Command !=
"F-nshs") && (ForwardEntryPtr->Command !=
"Sns-fsh") && (MainTrainDataPtr->
ActionVector.back().FormatType !=
Repeat))
14717 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat item");
14722 if(ForwardEntryPtr->LocationName ==
"")
14724 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
14725 ". One or other service does not have a location set");
14732 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
14733 ". One or other service does not have a location set");
14738 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
14740 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + NonRepeatingHeadCode +
14741 " is at a different location to the referencing train " + MainHeadCode);
14746 if(ForwardEntryPtr->Command ==
"F-nshs")
14749 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
14751 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle in-link service " + MainHeadCode +
14752 " finish time not consistent with start time of shuttle service " + NonRepeatingHeadCode);
14758 if(ForwardEntryPtr->Command ==
"Fns-sh")
14762 MainTrainDataPtr->
ActionVector.back().RearStartOrRepeatMins, MainTrainDataPtr->
ActionVector.back().NumberOfRepeats))
14764 SecondPassMessage(GiveMessages,
"Error in timetable - service " + NonRepeatingHeadCode +
", which links out from shuttle service " + MainHeadCode +
14765 ", has the wrong start time. It should correspond to the finish time of the last shuttle.");
14771 if((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh"))
14774 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
14776 SecondPassMessage(GiveMessages,
"Error in timetable - the non repeating link service " + NonRepeatingHeadCode +
14777 " appears in the same sequence as the corresponding shuttle service " + MainHeadCode);
14795 if(ForwardEntryPtr->Command ==
"Sns-sh")
14797 if(ReverseEntryPtr->
Command !=
"F-nshs")
14799 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'F-nshs' event for the 'Sns-sh' train whose headcode is " +
14800 MainHeadCode +
" and is a new shuttle service formed from the service with headcode " + NonRepeatingHeadCode);
14806 if(ForwardEntryPtr->Command ==
"F-nshs")
14808 if(ReverseEntryPtr->
Command !=
"Sns-sh")
14810 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns-sh' event for the 'F-nshs' train whose headcode is " +
14811 MainHeadCode +
" and forms a new shuttle service with headcode " + NonRepeatingHeadCode);
14818 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
14829 if(ForwardEntryPtr->Command ==
"Sns-fsh")
14831 if(ReverseEntryPtr->
Command !=
"Fns-sh")
14834 "Error in timetable - unable to find a corresponding 'Fns-sh' event for the 'Sns-fsh' non-shuttle service whose headcode is " + MainHeadCode +
14835 " formed from a shuttle service with headcode " + NonRepeatingHeadCode);
14841 if(ForwardEntryPtr->Command ==
"Fns-sh")
14843 if(ReverseEntryPtr->
Command !=
"Sns-fsh")
14846 "Error in timetable - unable to find a corresponding 'Sns-fsh' event for the 'Fns-sh' shuttle service whose headcode is " + MainHeadCode +
14847 " and forms a new non-shuttle service with headcode " + NonRepeatingHeadCode);
14854 ForwardEntryPtr->NonRepeatingShuttleLinkEntryPtr = OtherTrainDataPtr;
14878 +
"," + AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes) +
"," + AnsiString(RepeatNumber));
14879 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
14880 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
14881 int RepeatSecs = RepeatMinutes * RepeatNumber * 60;
14883 if((ReverseSecs > (ForwardSecs + RepeatSecs + 10)) || (ReverseSecs < (ForwardSecs + RepeatSecs - 10)))
14907 throw Exception(
"Error - last entry in " + TDEntryPtr->
HeadCode +
" service is not a repeat - should have already found this error");
14910 AnsiString OriginalHeadCode = TDEntryPtr->
HeadCode;
14911 AnsiString LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
14913 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
14915 SecondPassMessage(GiveMessages,
"Error in timetable - last event in shuttle service " + TDEntryPtr->
HeadCode +
" is not 'Fns', 'Fns-sh' or 'Frh-sh'");
14920 while(LastActionCommand ==
"Fns")
14922 TDEntryPtr = (TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr;
14923 LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
14924 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
14927 "Error in timetable - last event in a continuation shuttle service (i.e links back to a shuttle) whose headcode is " + TDEntryPtr->
HeadCode +
14928 " is not 'Fns', 'Fns-sh' or 'Frh-sh'");
14935 if((TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr != ShuttleStartAddress)
14938 " is a shuttle finish, but it doesn't link back to the start of the original shuttle starting service " + OriginalHeadCode +
14939 ". The linking of two or more shuttles is not permitted.");
14959 ShowMessage(Message);
14977 ShowMessage(Message);
15016 AnsiString(ActionEventType) +
"," + LocationID);
15017 AnsiString BaseLog =
"", Prefix =
"", ErrorLog =
"", WarningStr =
"";
15022 Prefix =
" ERROR: ";
15025 Prefix =
" HELD: ";
15026 ErrorLog =
" can't enter railway, train obstructing entry position ";
15027 WarningStr =
" can't enter railway, train obstructing entry position ";
15032 Prefix =
" HELD: ";
15033 ErrorLog =
" can't enter railway, route set against it at entry position ";
15034 WarningStr =
" can't enter railway, route set against it at entry position ";
15039 Prefix =
" HELD: ";
15040 ErrorLog =
" can't be created, train obstructing ";
15041 WarningStr =
" can't be created, train obstructing ";
15046 Prefix =
" HELD: ";
15047 ErrorLog =
" can't be created on a locked route at ";
15048 WarningStr =
" can't be created on a locked route at ";
15053 Prefix =
" HELD: ";
15054 ErrorLog =
" can't enter on a locked route at ";
15055 WarningStr =
" can't enter on a locked route at ";
15060 Prefix =
" HELD: ";
15061 ErrorLog =
" can't be created, diverging points at ";
15062 WarningStr =
" can't be created, diverging points at ";
15067 ErrorLog =
" left railway unexpectedly at ";
15072 ErrorLog =
" left railway at an incorrect exit at ";
15077 ErrorLog =
" failed to split - location too short at ";
15078 WarningStr =
" failed to split, location too short at ";
15083 Prefix =
" HELD: ";
15084 ErrorLog =
" unable to split - other train obstructing at ";
15085 WarningStr =
" unable to split - other train obstructing at ";
15090 ErrorLog =
" stopped at buffers unexpectedly at position ";
15094 ErrorLog =
" failed to stop at ";
15099 ErrorLog =
" failed to split at ";
15104 ErrorLog =
" failed to be joined by other train at ";
15109 ErrorLog =
" failed to join other train at ";
15114 ErrorLog =
" failed to terminate at ";
15119 ErrorLog =
" failed to form new service at ";
15124 ErrorLog =
" failed to exit railway ";
15129 ErrorLog =
" failed to change direction at ";
15134 ErrorLog =
" failed to pass ";
15139 ErrorLog =
" facing buffers and unable to start at ";
15143 ErrorLog =
" DERAILED at position ";
15144 Prefix =
" DERAILMENT: ";
15149 ErrorLog =
" CRASHED INTO BUFFERS at ";
15150 Prefix =
" CRASH: ";
15155 ErrorLog =
" CRASHED INTO ROAD TRAFFIC AT A LEVEL CROSSING at ";
15156 Prefix =
" CRASH: ";
15161 ErrorLog =
" CRASHED INTO " + OtherHeadCode +
" at position ";
15162 Prefix =
" CRASH: ";
15166 else if(ActionEventType ==
FailSPAD)
15168 ErrorLog =
" PASSED SIGNAL AT DANGER at position ";
15169 Prefix =
" SPAD: ";
15174 ErrorLog =
"Signals reset ahead of train, route cancelled at position ";
15175 Prefix =
" SPAD RISK: ";
15180 ErrorLog =
" forced a route cancellation by occupying it incorrectly at ";
15184 Prefix =
" WARNING: ";
15185 ErrorLog =
" waiting to join " + OtherHeadCode +
" at ";
15186 WarningStr =
" waiting to join " + OtherHeadCode +
" at ";
15191 Prefix =
" WARNING: ";
15192 ErrorLog =
" waiting to be joined by " + OtherHeadCode +
" at ";
15193 WarningStr =
" waiting to be joined by " + OtherHeadCode +
" at ";
15231 std::ofstream OutFile(
"TrainData.csv");
15235 ShowMessage(
"Output file TrainData.csv failed to open");
15242 OutFile <<
"HeadCode" <<
',' <<
"Description" <<
',' <<
"StartSpeed" <<
',' <<
"MaxRunningSpeed" <<
',' <<
"NumberOfTrains" <<
'\n' <<
'\n';
15247 OutFile <<
',' <<
"FormatType" <<
',' <<
"EventTime" <<
',' <<
"ArrivalTime" <<
',' <<
"DepartureTime" <<
',' <<
"LocationName" <<
',' <<
"Command" <<
15248 ',' <<
"OtherHeadCode" <<
',' <<
"LinkedTrainEntryPtr" <<
',' <<
"RearStartOrRepeatMins" <<
',' <<
"FrontStartOrRepeatDigits" <<
',' <<
15249 "RepeatNumber" <<
'\n' <<
'\n';
15250 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15253 AnsiString TimetableEntryTypeStr;
15259 TimetableEntryTypeStr =
"NoFormat";
15265 TimetableEntryTypeStr =
"TimeLoc";
15271 TimetableEntryTypeStr =
"TimeTimeLoc";
15277 TimetableEntryTypeStr =
"TimeCmd";
15283 TimetableEntryTypeStr =
"StartNew";
15289 TimetableEntryTypeStr =
"TimeCmdHeadCode";
15295 TimetableEntryTypeStr =
"FinRemHere";
15301 TimetableEntryTypeStr =
"FNSShuttle";
15307 TimetableEntryTypeStr =
"SNTShuttle";
15313 TimetableEntryTypeStr =
"SNSShuttle";
15319 TimetableEntryTypeStr =
"SNSNonRepeatFromShuttle";
15325 TimetableEntryTypeStr =
"FSHNewService";
15331 TimetableEntryTypeStr =
"Repeat";
15337 TimetableEntryTypeStr =
"Default";
15348 OutFile <<
',' <<
',' <<
"Mass" <<
',' <<
"MaxBrakeRate" <<
',' <<
"PowerAtRail" <<
',' <<
"TrainID" <<
',' <<
"RunningEntry" <<
'\n' <<
'\n';
15349 for(
unsigned int y = 0; y <
TrainDataVector.at(x).TrainOperatingDataVector.size(); y++)
15352 AnsiString RunningEntryStr;
15358 RunningEntryStr =
"NotStarted";
15364 RunningEntryStr =
"Running";
15370 RunningEntryStr =
"Exited";
15374 OutFile <<
',' <<
',' << TOD.
TrainID <<
',' << RunningEntryStr.c_str() <<
',' <<
'\n';
15391 ShowMessage(Message);
15392 BaseTime = TDateTime::CurrentDateTime();
15406 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
15419 TTrain *NewTrain =
new TTrain(1, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
15421 for(
int x = 0; x < NumberOfTrains; x++)
15423 *NewTrain =
TTrain(2, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
15443 int NumberOfTrains;
15450 for(
int x = 0; x < NumberOfTrains; x++)
15487 for(
int x = 0; x < LockedRouteVectorSize; x++)
15494 LockedRouteObject.
LockStartTime = TDateTime(LockStartTimeDouble);
15505 int LockedRouteVectorSize;
15512 for(
int x = 0; x < LockedRouteVectorSize; x++)
15570 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
15578 ContinuationAutoSigObject.
PassoutTime = TDateTime(PassoutTimeDouble);
15589 int ContinuationAutoSigVectorSize;
15596 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
15666 if(AVFirstEntry.
Command ==
"Snt")
15690 CTEMMP.second = CTEEntry;
15697 throw Exception(
"Error, Last ActionVectorEntry not a repeat in BuildContinuationTrainExpectationMultiMap");
15705 CTEMMP.second = CTEEntry;
15726 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
15743 if((VecPos < 0) || (VecPos >= (
int)
TrainVector.size()))
15745 throw Exception(
"Out of Range Error, vector size: " + AnsiString(
TrainVector.size()) +
", VecPos: " + AnsiString(VecPos) +
" in TrainVectorAt");
15756 AnsiString RetStr =
"", PartStr =
"";
15871 AnsiString TTFileName = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
15875 TTFileName = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
15877 AnsiString ShortTTName =
"";
15879 for(
int x = TTFileName.Length(); x > 0; x--)
15881 if(TTFileName[x] ==
'\\')
15883 ShortTTName = TTFileName.SubString(x + 1, TTFileName.Length() - x - 4);
15888 ShowMessage(
"Creates two timetables named " + ShortTTName +
15889 " in the 'Formatted timetables' folder, one in service order in '.csv' format, and one in chronological order in '.txt' format");
15891 Screen->Cursor = TCursor(-11);
15893 AnsiString FormatNoDPStr =
"#######0";
15894 AnsiString TableTitle =
"", TimetableTimeStr =
"", MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"", FirstHeadCode =
"", Header =
"";
15897 TableTitle =
"Railway: " + RailwayTitle +
"; Timetable: " + TimetableTitle +
"; Start time: " + TimetableTimeStr;
15904 MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"";
15906 if(TrainDataEntry.
Mass > 0)
15908 MassStr =
"; Mass " + AnsiString::FormatFloat(FormatNoDPStr, ((
double)TrainDataEntry.
Mass) / 1000) +
"Te; ";
15912 PowerStr =
"Power " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
PowerAtRail / 1000 / 0.8) +
"kW; ";
15916 BrakeStr =
"Brake force " + AnsiString::FormatFloat(FormatNoDPStr, (TrainDataEntry.
MaxBrakeRate * TrainDataEntry.
Mass / 9810)) +
"Te; ";
15920 MaxSpeedStr =
"Maximum speed " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
MaxRunningSpeed) +
" km/h";
15922 FirstHeadCode = TrainDataEntry.
HeadCode;
15923 int IncDigits = 0, IncMinutes = 0;
15925 if(!ActionVector.empty())
15927 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
15929 IncDigits = ActionVector.at(ActionVector.size() - 1).FrontStartOrRepeatDigits;
15930 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
15938 if((TrainDataEntry.
Description !=
"") && (MassStr !=
""))
15940 OneTTLine.
Header = TrainDataEntry.
Description + MassStr + PowerStr + BrakeStr + MaxSpeedStr;
15948 for(
unsigned int z = 0; z < ActionVector.size(); z++)
15953 AnsiString PartStr =
"", TimeStr =
"";
15970 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
15974 PartStr =
"Created at " + ActionVectorEntry.
LocationName;
15984 PartStr =
"Enters at " + LocName;
15997 PartStr =
"Created at " + LocName;
16011 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
16016 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
16022 else if(ActionVectorEntry.
Command ==
"Sfs")
16024 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" split from";
16028 else if(ActionVectorEntry.
Command ==
"Sns")
16030 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
16038 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
16044 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
16052 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
16055 AnsiString FirstHeadCode = TDE->
HeadCode;
16059 TimeStr =
GetRepeatHeadCode(36, FirstHeadCode, LastRepeatNumber, IncrementalDigits) +
" at " +
16071 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
16073 OneTTEntry.
Action = PartStr;
16074 OneTTEntry.
Time = TimeStr;
16076 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
16081 PartStr =
"Arrives & departs " + ActionVectorEntry.
LocationName;
16087 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
16092 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
16100 else if(ActionVectorEntry.
Command ==
"jbo")
16102 PartStr =
"Joined at " + ActionVectorEntry.
LocationName +
" by";
16106 else if(ActionVectorEntry.
Command ==
"fsp")
16108 PartStr =
"Splits from front at " + ActionVectorEntry.
LocationName +
" to form";
16112 else if(ActionVectorEntry.
Command ==
"rsp")
16114 PartStr =
"Splits from rear at " + ActionVectorEntry.
LocationName +
" to form";
16118 else if(ActionVectorEntry.
Command ==
"cdt")
16120 PartStr =
"Changes direction at " + ActionVectorEntry.
LocationName;
16126 if(ActionVectorEntry.
Command ==
"Fns")
16128 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
16132 else if(ActionVectorEntry.
Command ==
"F-nshs")
16134 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
16140 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service ";
16147 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
16153 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
16160 PartStr =
"Terminates shuttle service at " + ActionVectorEntry.
LocationName;
16165 else if(ActionVectorEntry.
Command ==
"Frh")
16167 PartStr =
"Terminates at " + ActionVectorEntry.
LocationName;
16172 if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
16176 else if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
16186 else if(ActionVectorEntry.
Command ==
"Fer")
16188 AnsiString AllowedExits;
16192 else if(ActionVectorEntry.
Command ==
"Fjo")
16194 PartStr =
"At " + ActionVectorEntry.
LocationName +
" joins";
16203 OneTTEntry.
Action = PartStr;
16204 OneTTEntry.
Time = TimeStr;
16211 AllTTTrains->push_back(OneTTLine);
16215 std::ofstream TTFile(TTFileName.c_str());
16219 StopTTClockMessage(64,
"Formatted timetable file failed to open - can't be created");
16220 delete AllTTTrains;
16255 TTFile << TableTitle.c_str() <<
'\n' <<
'\n';
16256 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
16258 TTFile << AllTTTrains->at(x).Header.c_str();
16261 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
16263 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
16265 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str() <<
',';
16269 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str();
16272 TTFile <<
'\n' <<
'\n';
16274 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.size(); z++)
16276 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.at(z).Action.c_str() <<
',';
16277 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
16279 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
16281 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str() <<
',';
16285 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str();
16290 TTFile <<
'\n' <<
'\n';
16295 AnsiString TTFileName2 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
16297 TTFileName2 = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName2 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".txt";
16299 std::ofstream TTFile2(TTFileName2.c_str());
16303 StopTTClockMessage(67,
"Chronological timetable file failed to open - can't be created");
16304 delete AllTTTrains;
16308 typedef std::multimap<AnsiString, AnsiString>TAnsiMultiMap;
16309 std::multimap<AnsiString, AnsiString>::iterator AMMIT;
16310 std::pair<AnsiString, AnsiString>AnsiMultiMapEntry;
16312 TAnsiMultiMap *TAMM =
new TAnsiMultiMap;
16317 TTFile2 << TableTitle.c_str() <<
'\n' <<
'\n';
16318 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
16320 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
16322 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.size(); z++)
16324 bool GiveMessagesFalse =
false;
16325 AnsiString TimeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time;
16326 AnsiString HeadCodeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode;
16327 AnsiString ActionString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Action;
16332 AnsiString OtherHeadCode = TimeString.SubString(1, 4);
16333 TimeString = TimeString.SubString(9, 5);
16334 ActionString +=
" " + OtherHeadCode;
16336 if(TimeString.SubString(1, 7) ==
"End at ")
16339 TimeString = TimeString.SubString(8, 5);
16341 AnsiString OneLine = TimeString +
' ' + HeadCodeString +
' ' + ActionString +
'\n';
16342 AnsiMultiMapEntry.first = TimeString;
16343 AnsiMultiMapEntry.second = OneLine;
16344 TAMM->insert(AnsiMultiMapEntry);
16349 for(AMMIT = TAMM->begin(); AMMIT != TAMM->end(); AMMIT++)
16351 TTFile2 << (AMMIT->second).c_str();
16353 delete AllTTTrains;
16362 bool AtLocChecked,
bool DirChecked,
int ArrRange,
int DepRange)
16366 bool AnalysisError =
false;
16367 AnsiString SequenceLog =
"SequenceLog\n";
16409 TTrainDataVector::iterator TDVIt, TDVCopyIt;
16411 int IteratorNumber = 0;
16412 AnsiString AnsiSuffix =
"";
16417 for(TDVCopyIt = TrainDataVectorCopy.begin() + IteratorNumber; TDVCopyIt != TrainDataVectorCopy.end(); TDVCopyIt++)
16419 if(TDVCopyIt->ServiceReference == TDVIt->ServiceReference)
16422 AnsiSuffix = AnsiString(Suffix);
16423 TDVCopyIt->ServiceReference = TDVIt->ServiceReference +
"/" + AnsiSuffix;
16427 SequenceLog +=
"1\n";
16430 std::pair<AnsiString, TServiceCallingLocsList> AllServiceCallingLocsEntry;
16431 for(
unsigned int x = 0; x < TrainDataVectorCopy.size(); x++)
16436 ServiceCallingLocsList.clear();
16437 if(ActionVector.empty())
16441 if(ActionVector.at(0).SignallerControl)
16445 for(
unsigned int z = 0; z < ActionVector.size(); z++)
16463 int HLoc = TE.
HLoc;
16464 int VLoc = TE.
VLoc;
16465 AnsiString HString;
16466 AnsiString VString;
16469 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
16473 HString = AnsiString(HLoc);
16477 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
16481 VString = AnsiString(VLoc);
16483 ServiceCallingLocsList.push_back(HString +
'-' + VString);
16506 else if(AVE.
Command ==
"cdt")
16508 if(ActionVector.at(z-1).SequenceType ==
Start)
16512 else if(ActionVector.at(z+1).SequenceType ==
Finish)
16519 ServiceCallingLocsList.push_back(
"%%%" + TimeString);
16528 ServiceCallingLocsList.push_back(LName);
16532 int HLoc = TE.
HLoc;
16533 int VLoc = TE.
VLoc;
16534 AnsiString HString;
16535 AnsiString VString;
16538 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
16542 HString = AnsiString(HLoc);
16546 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
16550 VString = AnsiString(VLoc);
16552 ServiceCallingLocsList.push_back(HString +
'-' + VString);
16556 AllServiceCallingLocsEntry.second = ServiceCallingLocsList;
16560 SequenceLog +=
"2\n";
16590 ShowMessage(
"Unable to create a program-readable timetable - please check the timetable file validity");
16596 bool NumPlatsAtThisLocCalculated =
false, ArrivalsPrinted =
false, DeparturesPrinted =
false, AtLocsPrinted =
false;
16597 AnsiString PreviousService =
"", PreviousServiceAndRepeatNumTotalOutput =
"", BasicTime =
"", MinuteString =
"", LastAnsiTime =
"";
16598 int NumTrains = 0, NumPlats = 0, LastFrhCount = 0, FrhCount = 0, NumTrainsAtLoc = 0;
16600 SequenceLog +=
"3\n";
16602 for(
unsigned int x = 0; x < TrainDataVectorCopy.size(); x++)
16607 TDateTime LastTDTime;
16608 int IncMinutes = 0;
16610 if(ActionVector.empty())
16614 if(ActionVector.at(0).SignallerControl)
16618 if(AVLast->FormatType ==
Repeat)
16620 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
16628 if(AVLast->ArrivalTime != TDateTime(-1))
16630 LastTDTime = AVLast->ArrivalTime;
16632 else if(AVLast->EventTime != TDateTime(-1))
16634 LastTDTime = AVLast->EventTime;
16653 SequenceLog +=
"4\n";
16685 for(
unsigned int x = 0; x < TrainDataVectorCopy.size(); x++)
16690 int IncMinutes = 0;
16692 if(ActionVector.empty())
16696 if(ActionVector.at(0).SignallerControl)
16700 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
16702 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
16704 for(
int y = 0; y < NumTrains; y++)
16718 for(
unsigned int z = 0; z < ActionVector.size(); z++)
16733 LocServiceTimesVector.push_back(TLSTEntry);
16736 AnsiString IncTime =
"", FoundStopTime =
"";
16737 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
16739 if(ActionVector.at(a).FormatType ==
TimeLoc)
16744 if(ActionVector.at(a).SequenceType ==
Finish)
16750 if(FoundStopTime ==
"")
16752 throw Exception(
"Failure to determine FoundStopTime for located Snt");
16754 int WhileCount = 0;
16763 if(IncTime >= FoundStopTime)
16767 LocServiceTimesVector.push_back(TLSTEntry);
16768 if(WhileCount > 2000)
16770 throw Exception(
"While loop failed to break in 2000 loops for located Snt");
16783 int HLoc = TE.
HLoc;
16784 int VLoc = TE.
VLoc;
16785 AnsiString HString;
16786 AnsiString VString;
16789 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
16793 HString = AnsiString(HLoc);
16797 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
16801 VString = AnsiString(VLoc);
16803 TLSTEntry.
Location = HString +
'-' + VString;
16807 LocServiceTimesVector.push_back(TLSTEntry);
16815 LocServiceTimesVector.push_back(TLSTEntry);
16817 AnsiString IncTime =
"", FoundStopTime =
"";
16818 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
16820 if(ActionVector.at(a).FormatType ==
TimeLoc)
16825 if(ActionVector.at(a).SequenceType ==
Finish)
16831 if(FoundStopTime ==
"")
16833 throw Exception(
"Failure to determine FoundStopTime for SequenceType == Start");
16835 int WhileCount = 0;
16844 if(IncTime >= FoundStopTime)
16848 LocServiceTimesVector.push_back(TLSTEntry);
16849 if(WhileCount > 2000)
16851 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == Start");
16861 bool SkipAddingMinutes =
false;
16864 LocServiceTimesVector.push_back(TLSTEntry);
16866 AnsiString IncTime =
"", FoundStopTime =
"";
16867 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
16869 if(ActionVector.at(a).FormatType ==
TimeLoc)
16874 if(ActionVector.at(a).SequenceType ==
Finish)
16877 if((a <= (z + 2)) && (FoundStopTime == TLSTEntry.
ArrTime) && ((ActionVector.at(a).LinkedTrainEntryPtr > 0) || (ActionVector.at(a).NonRepeatingShuttleLinkEntryPtr > 0)))
16881 LocServiceTimesVector.pop_back();
16882 SkipAddingMinutes =
true;
16887 if(FoundStopTime ==
"")
16889 throw Exception(
"Failure to determine FoundStopTime for SequenceType == Start");
16891 if(!SkipAddingMinutes)
16893 int WhileCount = 0;
16902 if(IncTime >= FoundStopTime)
16906 LocServiceTimesVector.push_back(TLSTEntry);
16907 if(WhileCount > 2000)
16909 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == Start");
16918 if((TLSTEntry.
Location == LocServiceTimesVector.back().Location) && (TLSTEntry.
ServiceAndRepeatNum == LocServiceTimesVector.back().ServiceAndRepeatNum))
16920 if(TLSTEntry.
DepTime == LocServiceTimesVector.back().ArrTime)
16922 TLSTEntry.
ArrTime = LocServiceTimesVector.back().ArrTime;
16923 LocServiceTimesVector.pop_back();
16924 LocServiceTimesVector.push_back(TLSTEntry);
16929 LocServiceTimesVector.push_back(TLSTEntry);
16935 LocServiceTimesVector.push_back(TLSTEntry);
16954 LocServiceTimesVector.push_back(TLSTEntry);
16958 AnsiString TempDepTime = TLSTEntry.
DepTime;
16960 LocServiceTimesVector.push_back(TLSTEntry);
16962 while(TLSTEntry.
AtLocTime < TempDepTime)
16967 TLSTEntry.
DepTime = TempDepTime;
16968 LocServiceTimesVector.push_back(TLSTEntry);
16972 LocServiceTimesVector.push_back(TLSTEntry);
16983 LocServiceTimesVector.push_back(TLSTEntry);
16986 LocServiceTimesVector.push_back(TLSTEntry);
17003 AnsiString HString;
17004 AnsiString VString;
17007 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
17011 HString = AnsiString(HLoc);
17015 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
17019 VString = AnsiString(VLoc);
17021 TLSTEntry.
Location = HString +
'-' + VString;
17023 LocServiceTimesVector.push_back(TLSTEntry);
17028 AnsiString FrhTime;
17029 if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
17033 else if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
17041 LocServiceTimesVector.push_back(TLSTEntry);
17047 LocServiceTimesVector.push_back(TLSTEntry);
17052 else if(AVE.
Command ==
"Frh-sh")
17054 if(y == NumTrains - 1)
17060 LocServiceTimesVector.push_back(TLSTEntry);
17066 LocServiceTimesVector.push_back(TLSTEntry);
17079 SequenceLog +=
"5\n";
17107 TLocServiceTimesVector::iterator Ptr1, Ptr2;
17110 AnsiString TTFileName3 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
17111 TTFileName3 = CurDir +
"\\Formatted timetables\\Conflict Analysis " + TTFileName3 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
17113 std::ofstream TTFile3(TTFileName3.c_str());
17117 ShowMessage(
"Conflict Analysis file failed to open - can't be created");
17121 if(LocServiceTimesVector.empty())
17123 ShowMessage(
"No timetabled services found");
17125 DeleteFile(TTFileName3);
17129 TTFile3 <<
"Timetable analysis for timetable: '" + TimetableTitle +
"' in conjunction with railway: '" + RailwayTitle +
"'\n";
17130 TTFile3 <<
"See user manual or on-screen help section 5.12 for detailed information.\n\n\n";
17131 SequenceLog +=
"6\n";
17180 Ptr1 = LocServiceTimesVector.begin();
17182 while(Ptr2 != LocServiceTimesVector.end())
17184 while(Ptr2->Location == Ptr1->Location)
17187 if(Ptr2 == LocServiceTimesVector.end())
17194 if(Ptr2 != LocServiceTimesVector.end())
17202 TTFile3 <<
"Arrival & pass analysis: an asterisk means that the number of same approach code arrivals and passes is equal to or greater than the number of platforms.\n";
17203 TTFile3 <<
"If the total number of arrivals and passes at the same time exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
17204 MinuteString =
" minutes";
17205 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
17208 MinuteString =
" minute";
17210 TTFile3 <<
"Location,Number of,Number of,Services arriving within " << AnsiString(ArrRange) << MinuteString <<
" with their arrival times and approach codes\n";
17211 TTFile3 <<
",Platforms,Trains\n\n";
17213 Ptr1 = LocServiceTimesVector.begin();
17215 while(Ptr2 != LocServiceTimesVector.end())
17217 PreviousService =
"";
17218 NumTrainsAtLoc = 0;
17219 ServiceAndRepeatNumTotal =
"";
17221 NumPlatsAtThisLocCalculated =
false;
17223 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
17225 PreviousService =
"";
17226 NumTrainsAtLoc = 0;
17227 ServiceAndRepeatNumTotal =
"";
17229 NumPlatsAtThisLocCalculated =
false;
17233 if(Ptr2 == LocServiceTimesVector.end())
17238 if(Ptr2 == LocServiceTimesVector.end())
17242 while(Ptr2->Location == Ptr1->Location)
17244 PreviousService =
"";
17245 NumTrainsAtLoc = 0;
17246 ServiceAndRepeatNumTotal =
"";
17247 BasicTime = Ptr1->ArrTime;
17248 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
17252 while(!
WithinTimeRange(0, BasicTime, Ptr2->ArrTime, ArrRange) || ((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
"")))
17254 BasicTime = Ptr2->ArrTime;
17257 if(Ptr2 == LocServiceTimesVector.end())
17261 if(Ptr2->Location != Ptr1->Location)
17266 if(Ptr2 == LocServiceTimesVector.end())
17270 if(Ptr2->Location != Ptr1->Location)
17276 if((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
""))
17280 if(!NumPlatsAtThisLocCalculated)
17283 NumPlatsAtThisLocCalculated =
true;
17285 if(Ptr1->ServiceAndRepeatNum != PreviousService)
17287 if(ServiceAndRepeatNumTotal ==
"")
17289 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
17290 NumTrainsAtLoc = 1;
17294 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
17297 PreviousService = Ptr2->ServiceAndRepeatNum;
17298 if(ServiceAndRepeatNumTotal ==
"")
17300 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
17301 NumTrainsAtLoc = 1;
17305 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
17309 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(2, BasicTime, Ptr2->ArrTime, ArrRange)))
17311 int MaxNumberOfSameDirections = 0;
17312 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
true, AnalysisError, MaxNumberOfSameDirections);
17317 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
17321 AnsiString Asterisk =
"";
17322 if(MaxNumberOfSameDirections >= NumPlats)
17327 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
17328 ArrivalsPrinted =
true;
17329 ServiceAndRepeatNumTotal =
"";
17331 if(Ptr2 == LocServiceTimesVector.end())
17335 if(Ptr2->Location != Ptr1->Location)
17340 if(Ptr2 == LocServiceTimesVector.end())
17346 if(!ArrivalsPrinted)
17348 TTFile3 <<
"Nothing to report for arrivals";
17353 SequenceLog +=
"7\n";
17358 Ptr1 = LocServiceTimesVector.begin();
17360 while(Ptr2 != LocServiceTimesVector.end())
17362 while(Ptr2->Location == Ptr1->Location)
17365 if(Ptr2 == LocServiceTimesVector.end())
17372 if(Ptr2 != LocServiceTimesVector.end())
17379 TTFile3 <<
"Departure & pass analysis: an asterisk means that the number of same exit code departures and passes is equal to or greater than the number of platforms.\n";
17380 TTFile3 <<
"If the total number of departures and passes at the same time exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
17381 MinuteString =
" minutes";
17382 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
17385 MinuteString =
" minute";
17387 TTFile3 <<
"Location,Number of,Number of,Services departing within " << AnsiString(DepRange) << MinuteString <<
" with their departure times and exit codes\n";
17388 TTFile3 <<
",Platforms,Trains\n\n";
17390 Ptr1 = LocServiceTimesVector.begin();
17392 while(Ptr2 != LocServiceTimesVector.end())
17394 PreviousService =
"";
17395 NumTrainsAtLoc = 0;
17396 ServiceAndRepeatNumTotal =
"";
17398 NumPlatsAtThisLocCalculated =
false;
17400 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
17402 PreviousService =
"";
17403 NumTrainsAtLoc = 0;
17404 ServiceAndRepeatNumTotal =
"";
17406 NumPlatsAtThisLocCalculated =
false;
17410 if(Ptr2 == LocServiceTimesVector.end())
17415 if(Ptr2 == LocServiceTimesVector.end())
17419 while(Ptr2->Location == Ptr1->Location)
17421 PreviousService =
"";
17422 NumTrainsAtLoc = 0;
17423 ServiceAndRepeatNumTotal =
"";
17424 BasicTime = Ptr1->DepTime;
17425 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
17429 while(!
WithinTimeRange(3, BasicTime, Ptr2->DepTime, DepRange) || ((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
"")))
17431 BasicTime = Ptr2->DepTime;
17434 if(Ptr2 == LocServiceTimesVector.end())
17438 if(Ptr2->Location != Ptr1->Location)
17443 if(Ptr2 == LocServiceTimesVector.end())
17447 if(Ptr2->Location != Ptr1->Location)
17453 if((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
""))
17457 if(!NumPlatsAtThisLocCalculated)
17460 NumPlatsAtThisLocCalculated =
true;
17462 if(Ptr1->ServiceAndRepeatNum != PreviousService)
17464 if(ServiceAndRepeatNumTotal ==
"")
17466 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
17467 NumTrainsAtLoc = 1;
17471 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
17474 PreviousService = Ptr2->ServiceAndRepeatNum;
17475 if(ServiceAndRepeatNumTotal ==
"")
17477 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
17478 NumTrainsAtLoc = 1;
17482 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
17486 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(5, BasicTime, Ptr2->DepTime, DepRange)))
17488 int MaxNumberOfSameDirections = 0;
17489 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(3, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
false, AnalysisError, MaxNumberOfSameDirections);
17494 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
17498 AnsiString Asterisk =
"";
17499 if(MaxNumberOfSameDirections >= NumPlats)
17504 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
17505 DeparturesPrinted =
true;
17506 ServiceAndRepeatNumTotal =
"";
17508 if(Ptr2 == LocServiceTimesVector.end())
17512 if(Ptr2->Location != Ptr1->Location)
17517 if(Ptr2 == LocServiceTimesVector.end())
17523 if(!DeparturesPrinted)
17525 TTFile3 <<
"Nothing to report for departures";
17530 SequenceLog +=
"8\n";
17537 Ptr1 = LocServiceTimesVector.begin();
17539 while(Ptr2 != LocServiceTimesVector.end())
17541 while(Ptr2->Location == Ptr1->Location)
17544 if(Ptr2 == LocServiceTimesVector.end())
17551 if(Ptr2 != LocServiceTimesVector.end())
17558 TTFile3 <<
"Trains present at location analysis: an asterisk means that the number of trains at the location is greater than the number of platforms.\n\n";
17559 TTFile3 <<
"Location,Number of,Number of,Time,Services at the location at that time\n";
17560 TTFile3 <<
",Platforms,Trains,\n\n";
17561 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
17562 Ptr1 = LocServiceTimesVector.begin();
17564 while(Ptr2 != LocServiceTimesVector.end())
17566 PreviousService =
"";
17567 ServiceAndRepeatNumTotal =
"";
17568 NumTrainsAtLoc = 0;
17570 NumPlatsAtThisLocCalculated =
false;
17572 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
17574 PreviousService =
"";
17575 ServiceAndRepeatNumTotal =
"";
17576 NumTrainsAtLoc = 0;
17578 NumPlatsAtThisLocCalculated =
false;
17582 if(Ptr2 == LocServiceTimesVector.end())
17587 if(Ptr2 == LocServiceTimesVector.end())
17591 while(Ptr2->Location == Ptr1->Location)
17593 if(Ptr1->FrhMarker ==
"Frh")
17596 Ptr1->FrhMarker =
"FrhCounted";
17598 PreviousService =
"";
17599 NumTrainsAtLoc = 0;
17600 ServiceAndRepeatNumTotal =
"";
17601 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
17605 while((Ptr2->AtLocTime != Ptr1->AtLocTime) || ((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
"")))
17608 if(Ptr1->FrhMarker ==
"Frh")
17611 Ptr1->FrhMarker =
"FrhCounted";
17614 if(Ptr2 == LocServiceTimesVector.end())
17618 if(Ptr2->Location != Ptr1->Location)
17623 if(Ptr2 == LocServiceTimesVector.end())
17627 if(Ptr2->Location != Ptr1->Location)
17631 while(Ptr2->AtLocTime == Ptr1->AtLocTime)
17633 if((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
""))
17637 if(!NumPlatsAtThisLocCalculated)
17640 NumPlatsAtThisLocCalculated =
true;
17642 if(Ptr1->ServiceAndRepeatNum != PreviousService)
17644 if(ServiceAndRepeatNumTotal ==
"")
17646 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum;
17647 NumTrainsAtLoc = 1;
17651 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum;
17654 PreviousService = Ptr2->ServiceAndRepeatNum;
17655 if(ServiceAndRepeatNumTotal ==
"")
17657 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum;
17658 NumTrainsAtLoc = 1;
17662 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum;
17665 if(Ptr1->FrhMarker ==
"Frh")
17668 Ptr1->FrhMarker =
"FrhCounted";
17671 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (Ptr2->AtLocTime != Ptr1->AtLocTime))
17675 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTAtLoc(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc);
17677 if((NumTrainsAtLoc > 1) && ((FrhCount < NumTrainsAtLoc) || (FrhCount != LastFrhCount)))
17679 AnsiString Asterisk =
"";
17680 if(NumTrainsAtLoc > NumPlats)
17687 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
17689 else if(FrhCount == 1)
17691 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (1 remains here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
17695 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (" << FrhCount <<
" remain here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
17697 LastFrhCount = FrhCount;
17698 PreviousServiceAndRepeatNumTotalOutput = ServiceAndRepeatNumTotalOutput;
17699 AtLocsPrinted =
true;
17700 ServiceAndRepeatNumTotal =
"";
17703 if(Ptr2 == LocServiceTimesVector.end())
17707 if(Ptr2->Location != Ptr1->Location)
17712 if(Ptr2 == LocServiceTimesVector.end())
17720 TTFile3 <<
"Nothing to report for trains at locations";
17725 SequenceLog +=
"9\n";
17755 TTrainDataEntry SingleServiceEntry, PartServiceEntry, NewPartServiceEntry, TempEntry;
17760 TTFile3 <<
"Train direction analysis - consisting of train facing directions on creation and possible missing or questionable changes of direction:\n\n";
17761 for(
unsigned int x = 0; x < TrainDataVectorCopy.size(); x++)
17769 if((AV.at(0).Command ==
"Snt") || (AV.at(0).Command ==
"Snt-sh"))
17771 SingleServiceEntry = TDE;
17773 for(
unsigned int y = 0; y < SSAV.size(); y++)
17775 if((SSAV.at(y).Command ==
"Fjo") || (SSAV.at(y).Command ==
"Frh") || (SSAV.at(y).Command ==
"Fer") || (SSAV.at(y).Command ==
"Frh-sh"))
17777 SingleServiceVector.push_back(SingleServiceEntry);
17780 else if((SSAV.at(y).Command ==
"fsp") || (SSAV.at(y).Command ==
"rsp"))
17782 PartServiceEntry = TDE;
17784 for(
unsigned int z = 0; z <= y; z++)
17789 PartServiceEntry.
ActionVector.at(z).Command =
"chr-sp";
17790 PartServiceEntry.
ActionVector.at(z).OtherHeadCode = PartServiceEntry.
ActionVector.at(z).LinkedTrainEntryPtr->ServiceReference;
17793 PartServiceVector.push_back(PartServiceEntry);
17794 if(SSAV.at(y).Command ==
"fsp")
17796 SSAV.at(y).Command =
"Front split - original service continues below";
17797 SSAV.at(y).OtherHeadCode =
"";
17799 if(SSAV.at(y).Command ==
"rsp")
17801 SSAV.at(y).Command =
"Rear split - original service continues below";
17802 SSAV.at(y).OtherHeadCode =
"";
17806 else if(SSAV.at(y).Command ==
"Fns")
17808 SSAV.at(y).Command =
"chr-Fns";
17809 SSAV.at(y).OtherHeadCode = SSAV.at(y).LinkedTrainEntryPtr->ServiceReference;
17810 PartServiceVector.push_back(SingleServiceEntry);
17813 else if(SSAV.at(y).Command ==
"Fns-sh")
17815 SSAV.at(y).Command =
"chr-Fns-sh";
17816 SSAV.at(y).OtherHeadCode = SSAV.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
17817 SSAV.at(y).NonRepeatingShuttleLinkHeadCode =
"";
17818 PartServiceVector.push_back(SingleServiceEntry);
17821 else if(SSAV.at(y).Command ==
"F-nshs")
17823 SSAV.at(y).Command =
"chr-F-nshs";
17824 SSAV.at(y).OtherHeadCode = SSAV.at(y).LinkedTrainEntryPtr->ServiceReference;
17825 SSAV.at(y).NonRepeatingShuttleLinkHeadCode =
"";
17826 PartServiceVector.push_back(SingleServiceEntry);
17832 SequenceLog +=
"10\n";
17836 AnsiString NextRef;
17837 while(!PartServiceVector.empty())
17839 PartServiceEntry = PartServiceVector.at(0);
17840 for(
unsigned int y = 0; y < PartServiceEntry.
ActionVector.size(); y++)
17842 if(PartServiceEntry.
ActionVector.at(y).Command.SubString(1,3) ==
"chr")
17844 NextRef = PartServiceEntry.
ActionVector.at(y).OtherHeadCode;
17848 bool FinishType =
true, FoundFlag =
false;
17855 for(
unsigned int y = 1; y < TempEntry.
ActionVector.size(); y++)
17859 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
17863 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
17869 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
17870 SingleServiceVector.push_back(PartServiceVector.at(0));
17871 PartServiceVector.erase(&PartServiceVector.at(0));
17876 NewPartServiceEntry = PartServiceVector.at(0);
17880 PartServiceVector.push_back(NewPartServiceEntry);
17883 TempEntry.
ActionVector.at(y).Command =
"Front split - original service continues below";
17888 TempEntry.
ActionVector.at(y).Command =
"Rear split - original service continues below";
17891 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
17893 else if(TempEntry.
ActionVector.at(y).Command ==
"Fns")
17896 NextRef = TempEntry.
ActionVector.at(y).LinkedTrainEntryPtr->ServiceReference;
17898 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
17901 else if(TempEntry.
ActionVector.at(y).Command ==
"Fns-sh")
17904 TempEntry.
ActionVector.at(y).OtherHeadCode = TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
17905 TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkHeadCode =
"";
17906 NextRef = TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
17907 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
17910 else if(TempEntry.
ActionVector.at(y).Command ==
"F-nshs")
17914 TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkHeadCode =
"";
17915 NextRef = TempEntry.
ActionVector.at(y).LinkedTrainEntryPtr->ServiceReference;
17916 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
17924 SequenceLog += +
"11\n";
17925 throw Exception(
"Unable to find service reference " + NextRef +
" Last ref checked = " + TempEntry.
ServiceReference);
17929 if(!PartServiceVector.empty())
17931 SequenceLog +=
"12\n";
17932 throw Exception(
"PartServiceVector should be empty here - size = " + PartServiceVector.size());
17934 SequenceLog +=
"13\n";
17979 bool BufferFacingUnReportedFlag =
true;
17980 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
17986 SequenceLog +=
"13a\n";
17987 throw Exception(
"Repeat entry present in SingleServiceVector at position " + x);
17990 if((AV.at(0).Command ==
"Snt") || (AV.at(0).Command ==
"Snt-sh"))
17992 bool BufferFlag =
false;
17993 int FrontTVPos = AV.at(0).FrontStartOrRepeatDigits;
17994 int RearTVPos = AV.at(0).RearStartOrRepeatMins;
17995 AnsiString FrontLocName = AV.at(0).LocationName;
17996 int NextEntryPos, NextExitPos;
17999 if(ThisElement.
Conn[0] == RearTVPos)
18003 else if(ThisElement.
Conn[1] == RearTVPos)
18007 else if(ThisElement.
Conn[2] == RearTVPos)
18011 else if(ThisElement.
Conn[3] == RearTVPos)
18023 if(ThisElement.
Conn[ThisExitPos] == -1)
18025 SequenceLog =
"13b\n";
18026 throw Exception(
"ThisElement connects to -1 for " + TDE.
ServiceReference);
18029 NextEntryPos = ThisElement.
ConnLinkPos[ThisExitPos];
18030 if((NextElement.
TrackType ==
Points) && ((NextEntryPos == 0) || (NextEntryPos == 2)))
18032 BufferFlag =
false;
18037 BufferFlag =
false;
18042 BufferFlag =
false;
18050 else if((NextElement.
TrackType ==
Points) && ((NextEntryPos == 1) || (NextEntryPos == 3)))
18052 ThisElement = NextElement;
18058 if(NextEntryPos == 0)
18062 else if(NextEntryPos == 1)
18066 else if(NextEntryPos == 2)
18070 else if(NextEntryPos == 3)
18075 ThisElement = NextElement;
18076 ThisExitPos = NextExitPos;
18081 if(BufferFacingUnReportedFlag)
18083 TTFile3 <<
"Train facing direction on creation analysis:-\n\n";
18084 BufferFacingUnReportedFlag =
false;
18086 TTFile3 <<
"Service " + TDE.
ServiceReference +
" facing buffers on creation\n";
18090 if(BufferFacingUnReportedFlag)
18092 TTFile3 <<
"Nothing to report for train facing directions\n\n";
18098 SequenceLog +=
"13c\n";
18101 AnsiString LocationNameToBeChecked =
"";
18102 bool MissingcdtUnreportedFlag =
true;
18104 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
18107 unsigned int y = 0;
18108 int FirstInstance = 9999, SecondInstance = 9999;
18109 bool FullBreak =
false;
18110 MarkerList.clear();
18117 while((y < TDEntry.
ActionVector.size()) && !FullBreak)
18126 LocationNameToBeChecked = TDEntry.
ActionVector.at(y).LocationName;
18128 for(
unsigned int z = y; z < TDEntry.
ActionVector.size(); z++)
18133 (AVEntry.
Command ==
"Frh-sh"))
18148 for(
unsigned int a = z; a < TDEntry.
ActionVector.size(); a++)
18154 if(TDEntry.
ActionVector.at(a).LocationName == LocationNameToBeChecked)
18156 SecondInstance = a;
18158 for(
unsigned int b = 0; b < TDEntry.
ActionVector.size(); b++)
18160 if(TDEntry.
ActionVector.at(b).Command.SubString(1,3) ==
"chr")
18162 Sequence = Sequence + AnsiString(
" -> ") + TDEntry.
ActionVector.at(b).OtherHeadCode;
18165 if(MissingcdtUnreportedFlag)
18167 TTFile3 <<
"Possibly missing changes of direction - these will be missing unless the service travels in a loop back to the locations marked:-\n\n";
18169 TTFile3 << LocationNameToBeChecked <<
" is listed twice with no direction change between in service sequence: " << Sequence <<
"\n\n";
18170 MarkerList.push_back(FirstInstance);
18171 MarkerList.push_back(SecondInstance);
18173 MissingcdtUnreportedFlag =
false;
18184 if(MissingcdtUnreportedFlag)
18186 TTFile3 <<
"Nothing to report for missing changes of direction\n\n";
18192 SequenceLog +=
"14\n";
18201 typedef std::list<AnsiString> TLocList;
18202 TLocList BackwardList, ForwardList;
18203 bool IntroLineNeeded =
true;
18204 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
18206 unsigned int cdtPosition = 9999;
18207 AnsiString cdtLocation =
"";
18208 bool FoundSameName =
false;
18209 MarkerList.clear();
18211 for(
unsigned int y = 0; y < TDEntry.
ActionVector.size(); y++)
18214 BackwardList.clear();
18215 ForwardList.clear();
18219 (AVEntry.
Command ==
"Frh-sh"))
18221 if(MarkerList.empty())
18228 for(
unsigned int b = 0; b < TDEntry.
ActionVector.size(); b++)
18230 if(TDEntry.
ActionVector.at(b).Command.SubString(1,3) ==
"chr")
18232 Sequence = Sequence + AnsiString(
" -> ") + TDEntry.
ActionVector.at(b).OtherHeadCode;
18236 if(IntroLineNeeded)
18238 TTFile3 <<
"Questionable change of direction analysis.\n\n";
18239 TTFile3 <<
"For marked changes of direction there are no same-name locations listed both above and below.\n";
18240 TTFile3 <<
"These changes of direction are probably valid for movements to and from depots but all should be checked to\n";
18241 TTFile3 <<
"make sure that none has been included incorrectly:\n\n";
18242 IntroLineNeeded =
false;
18244 TTFile3 <<
"Service sequence " << Sequence <<
" contains questionable changes of direction:-\n\n";
18256 for(
int z = y - 1; z >= 0; z--)
18259 if(AVEntry2.
Command ==
"cdt")
18268 BackwardList.sort();
18269 BackwardList.unique();
18270 for(
unsigned int z = y + 1; z < TDEntry.
ActionVector.size(); z++)
18284 ForwardList.sort();
18285 ForwardList.unique();
18286 FoundSameName =
false;
18288 if(!BackwardList.empty() && !ForwardList.empty())
18290 for(TLocList::iterator BLIt = BackwardList.begin(); BLIt != BackwardList.end(); BLIt++)
18292 for(TLocList::iterator FLIt = ForwardList.begin(); FLIt != ForwardList.end(); FLIt++)
18296 FoundSameName =
true;
18303 MarkerList.push_back(cdtPosition);
18307 if(IntroLineNeeded)
18309 TTFile3 <<
"Nothing to report for questionable changes of direction\n\n";
18325 SequenceLog +=
"15\n";
18331 catch(
const Exception &e)
18333 AnsiString TTErrorFileName =
"Analysis Error.txt";
18334 TTErrorFileName = CurDir +
"\\Formatted timetables\\" + TTErrorFileName;
18335 std::ofstream TTError(TTErrorFileName.c_str());
18338 ShowMessage(
"Analysis error file failed to open - can't be created");
18342 AnsiString TimeNow = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
18343 TTError << TimeNow.c_str() <<
'\n' << ArrRange <<
'\n' << ArrChecked <<
'\n' << DepRange <<
'\n' <<
18344 DepChecked <<
'\n' << AtLocChecked <<
'\n' << SequenceLog <<
'\n' << AnsiString(e.Message);
18347 ShowMessage(
"Error in Conflict Analysis: A file called 'Analysis Error.txt' has been created in your Formatted timetables folder. Please send this file together with your railway and timetable files to railwayfeedback@gmail.com for investigation - many thanks");
18357 if((SSVectorNumber < 0) || ((
unsigned int)SSVectorNumber >= SingleServiceVector.size()))
18359 throw Exception(
"SSVectorNumber out of range, = " + AnsiString(SSVectorNumber) +
", Vector size = " + SingleServiceVector.size());
18361 TTrainDataEntry SingleService = SingleServiceVector.at(SSVectorNumber);
18363 VecFile <<
",Initial service reference " << SingleService.
ServiceReference +
'\n';
18364 AnsiString Marker =
"";
18365 for(
unsigned int x = 0; x < SingleService.
ActionVector.size(); x++)
18368 for(
TNumListIterator MLIt = MarkerList.begin(); MLIt != MarkerList.end(); MLIt++)
18370 if(
int(x) == *MLIt)
18381 VecFile << Marker << AnsiString(AVE.
EventTime.TimeString()) <<
' ' << AVE.
Command <<
' ' << RearID <<
' ' << FrontID <<
'\n';
18387 VecFile << Marker << AnsiString(AVE.
EventTime.TimeString()) <<
' ' << AVE.
Command <<
' ' << RearID <<
' ' << FrontID <<
' ' << AVE.
OtherHeadCode <<
'\n';
18400 if(AVE.
Command.SubString(1,3) ==
"chr")
18409 AVE.
Command =
"Change of service to ";
18411 if(AVE.
Command.SubString(5, AVE.
Command.Length() - 4) ==
"Fns-sh")
18413 AVE.
Command =
"Change to shuttle finishing service";
18415 if(AVE.
Command.SubString(5, AVE.
Command.Length() - 4) ==
"F-nshs")
18438 VecFile << Marker << AnsiString(AVE.
EventTime.TimeString()) <<
' ' <<
"Pass" <<
' ' << AVE.
LocationName <<
'\n';
18442 AnsiString ListOfExits =
"";
18447 VecFile << Marker << AnsiString(AVE.
EventTime.TimeString()) <<
" Fer " << ListOfExits <<
'\n';
18451 VecFile << Marker <<
"Frh" <<
'\n';
18466 for(
unsigned int x = 0; x < Vector.size(); x++)
18470 if(Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 1).FormatType ==
Repeat)
18472 TActionVectorEntry AVE = Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 2);
18475 FinishType =
false;
18480 TActionVectorEntry AVE = Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 1);
18483 FinishType =
false;
18488 return(Vector.at(x));
18492 return(Vector.at(Vector.size() - 1));
18501 if((Time1 ==
"") || (Time2 ==
""))
18506 int Mins = Time1.SubString(4,2).ToInt();
18507 int Hours = Time1.SubString(1,2).ToInt();
18508 int Time1Mins = (Hours * 60) + Mins;
18509 Mins = Time2.SubString(4,2).ToInt();
18510 Hours = Time2.SubString(1,2).ToInt();
18511 int Time2Mins = (Hours * 60) + Mins;
18512 if(abs(Time1Mins - Time2Mins) <= MinuteRange)
18524 bool &AnalysisError,
int &MaxNumberOfSameDirections)
18531 AnsiString Output =
"", OneService =
"", TempStr1 =
"", TempStr2 =
"";
18533 std::list<AnsiString> ServiceList;
18535 bool EvenComma =
false;
18536 for(
int x = 1; x <= Input.Length(); x++)
18538 TempStr1 = Input[x];
18539 if(TempStr1 == AnsiString(
',') && EvenComma)
18545 TempStr2 += Input[x];
18547 if(TempStr1 == AnsiString(
','))
18549 EvenComma = !EvenComma;
18553 while(TempStr2.Length() > 0)
18555 SCPos = TempStr2.Pos(
';');
18558 OneService = TempStr2.SubString(1, SCPos - 1);
18559 ServiceList.push_back(OneService);
18560 TempStr2 = TempStr2.SubString(SCPos + 1, TempStr2.Length() - SCPos);
18564 ServiceList.push_back(TempStr2);
18568 ServiceList.sort();
18569 ServiceList.unique();
18570 NumTrainsAtLoc = ServiceList.size();
18573 int DirectionMarker = 0;
18575 std::list<AnsiString>::iterator SLIt, SLIt1, SLIt2, SLIt3;
18577 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
18579 *SLIt = *SLIt +
"&0";
18581 SLIt3 = ServiceList.end();
18583 AnsiString ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatInfo1, RepeatInfo2;
18584 int AmpersandPos, SpacePos, CommaPos1, CommaPos2, RepeatNum1, RepeatNum2;
18585 TAllServiceCallingLocsMap::iterator ASCLIt1, ASCLIt2;
18587 MaxNumberOfSameDirections = 0;
18588 int SameDirectionCount = 0;
18590 for(std::list<AnsiString>::iterator SLIt1 = ServiceList.begin(); SLIt1 != SLIt3; SLIt1++)
18594 if(SLIt1->SubString(SLIt1->Length() - 1, 2) != AnsiString(
"&0"))
18600 CommaPos1 = SLIt1->Pos(
',');
18601 ServiceRef1 = SLIt1->SubString(1, CommaPos1 - 1);
18603 SpacePos = ServiceRef1.Pos(
' ');
18607 RepeatInfo1 = ServiceRef1.SubString(SpacePos + 2, ServiceRef1.Length() - SpacePos - 2);
18608 ServiceRef1 = ServiceRef1.SubString(1, SpacePos - 1);
18609 if(RepeatInfo1[1] ==
'F')
18615 SpacePos = RepeatInfo1.Pos(
' ');
18616 RepeatNum1 = RepeatInfo1.SubString(SpacePos + 1, RepeatInfo1.Length() - SpacePos).ToInt();
18619 AnsiTime1 = SLIt1->SubString(CommaPos1 + 1, SLIt1->Length() - CommaPos1);
18621 AmpersandPos = AnsiTime1.Pos(
'&');
18622 AnsiTime1 = AnsiTime1.SubString(1, AmpersandPos - 1);
18627 throw Exception(
"ASCLIt1 Error in " + Input);
18629 ServiceCallingLocsList1 = ASCLIt1->second;
18630 AmpersandPos = SLIt1->Pos(
'&');
18631 *SLIt1 = SLIt1->SubString(1, AmpersandPos);
18632 *SLIt1 = *SLIt1 + AnsiString(++DirectionMarker);
18634 SameDirectionCount = 1;
18635 for(SLIt2 = SLIt; SLIt2 != ServiceList.end(); SLIt2++)
18637 CommaPos2 = SLIt2->Pos(
',');
18638 ServiceRef2 = SLIt2->SubString(1, CommaPos2 - 1);
18640 SpacePos = ServiceRef2.Pos(
' ');
18644 RepeatInfo2 = ServiceRef2.SubString(SpacePos + 2, ServiceRef2.Length() - SpacePos - 2);
18645 ServiceRef2 = ServiceRef2.SubString(1, SpacePos - 1);
18646 if(RepeatInfo2[1] ==
'F')
18652 SpacePos = RepeatInfo2.Pos(
' ');
18653 RepeatNum2 = RepeatInfo2.SubString(SpacePos + 1, RepeatInfo2.Length() - SpacePos).ToInt();
18656 AnsiTime2 = SLIt2->SubString(CommaPos2 + 1, SLIt2->Length() - CommaPos2);
18658 AmpersandPos = AnsiTime2.Pos(
'&');
18659 AnsiTime2 = AnsiTime2.SubString(1, AmpersandPos - 1);
18664 throw Exception(
"ASCLIt2 Error in " + Input);
18666 ServiceCallingLocsList2 = ASCLIt2->second;
18668 if(
SameDirection(0, ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatNum1, RepeatNum2, ServiceCallingLocsList1, ServiceCallingLocsList2, Location, Arrival))
18670 int AmpersandPos = SLIt2->Pos(
'&');
18671 *SLIt2 = SLIt2->SubString(1, AmpersandPos);
18672 *SLIt2 = *SLIt2 + AnsiString(DirectionMarker);
18673 SameDirectionCount++;
18676 if(SameDirectionCount > MaxNumberOfSameDirections)
18678 MaxNumberOfSameDirections = SameDirectionCount;
18683 if(SLIt3->SubString(SLIt3->Length() - 1, 2) == AnsiString(
"&0"))
18686 AmpersandPos = SLIt3->Pos(
'&');
18687 *SLIt3 = SLIt3->SubString(1, AmpersandPos);
18688 *SLIt3 = *SLIt3 + AnsiString(++DirectionMarker);
18691 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
18694 AmpersandPos = SLIt->Pos(
'&');
18695 AnsiString DirectionMarkerString = SLIt->SubString(AmpersandPos + 1, SLIt->Length() - AmpersandPos);
18696 AnsiString ServiceWithoutMarker = SLIt->SubString(1, AmpersandPos - 1);
18697 DirectionMarker = DirectionMarkerString.ToInt();
18698 AnsiString DirectionSuffix =
"";
18700 if(DirectionMarker < 27)
18702 c = 64 + DirectionMarker;
18703 DirectionSuffix =
"," + AnsiString(c);
18705 else if(DirectionMarker < 53)
18707 c = 65 + DirectionMarker - 27;
18708 DirectionSuffix =
",A" + AnsiString(c);
18712 DirectionSuffix =
",?";
18714 *SLIt = ServiceWithoutMarker + DirectionSuffix;
18717 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
18719 Output = Output + *SLIt +
",";
18721 if(Output.Length() > 0)
18723 Output = Output.SubString(1, Output.Length() - 1);
18729 catch(
const Exception &e)
18731 AnalysisError =
true;
18743 AnsiString InternalInput = Input, Output =
"", OneService =
"";
18745 std::list<AnsiString> ServiceList;
18747 while(InternalInput.Length() > 0)
18749 CommaPos = InternalInput.Pos(
',');
18752 OneService = InternalInput.SubString(1, CommaPos - 1);
18753 ServiceList.push_back(OneService);
18754 InternalInput = InternalInput.SubString(CommaPos + 1, InternalInput.Length() - CommaPos);
18758 ServiceList.push_back(InternalInput);
18759 InternalInput =
"";
18763 ServiceList.sort();
18764 ServiceList.unique();
18765 NumTrainsAtLoc = ServiceList.size();
18766 for(std::list<AnsiString>::iterator SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
18768 Output = Output + *SLIt +
",";
18770 if(Output.Length() > 0)
18772 Output = Output.SubString(1, Output.Length() - 1);
18785 AnsiString(RepeatNum1) +
"," + AnsiString(RepeatNum2) +
"," + Location);
18787 std::list<AnsiString>::iterator LP1 = 0, LP2 = 0, ListPtr1 = 0, ListPtr2 = 0, LocPtr1 = 0, LocPtr2 = 0;
18792 bool LocFound =
false;
18793 AnsiString Ref1 = Ref1In, Ref2 = Ref2In;
18795 TDateTime FirstServiceTime;
18798 int Ref1Target = 0, Ref1Count = 0;
18799 int SlashPos = Ref1.Pos(
'/');
18802 Ref1Target = Ref1.SubString(SlashPos + 1, Ref1.Length() - SlashPos).ToInt();
18803 Ref1 = Ref1.SubString(1, SlashPos - 1);
18805 int Ref2Target = 0, Ref2Count = 0;
18806 SlashPos = Ref2.Pos(
'/');
18809 Ref2Target = Ref2.SubString(SlashPos + 1, Ref2.Length() - SlashPos).ToInt();
18810 Ref2 = Ref2.SubString(1, SlashPos - 1);
18812 for(ListPtr1 = List1.begin(); ListPtr1 != List1.end(); ListPtr1++)
18815 if((*ListPtr1) == Location)
18817 LocPtr1 = ListPtr1;
18820 if(ListPtr1->SubString(1, 3) ==
"%%%")
18822 AnsiString CDTTime = ListPtr1->SubString(4, 5);
18827 FirstServiceTime = TDateTime(-1);
18828 bool BreakFlag =
false;
18831 if(TDVIt->ServiceReference == Ref1)
18833 if(Ref1Target > Ref1Count)
18838 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
18839 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
18843 FirstServiceTime = AVIt->EventTime;
18849 FirstServiceTime = AVIt->ArrivalTime;
18855 FirstServiceTime = AVIt->DepartureTime;
18866 if(IncMinutes == -1)
18868 throw Exception(
"Failed to find service for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
18870 if(FirstServiceTime == TDateTime(-1))
18872 throw Exception(
"Failed to find first service time for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
18876 if(!Arrival && (Time1 == CDTTime))
18881 if(Arrival && (Time1 == CDTTime))
18885 if(Time1 > CDTTime)
18890 if(Time1 < CDTTime)
18903 for(ListPtr2 = List2.begin(); ListPtr2 != List2.end(); ListPtr2++)
18905 if((*ListPtr2) == Location)
18907 LocPtr2 = ListPtr2;
18910 if(ListPtr2->SubString(1, 3) ==
"%%%")
18912 AnsiString CDTTime = ListPtr2->SubString(4, 5);
18917 FirstServiceTime = TDateTime(-1);
18918 bool BreakFlag =
false;
18921 if(TDVIt->ServiceReference == Ref2)
18923 if(Ref2Target > Ref2Count)
18928 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
18929 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
18933 FirstServiceTime = AVIt->EventTime;
18939 FirstServiceTime = AVIt->ArrivalTime;
18945 FirstServiceTime = AVIt->DepartureTime;
18956 if(IncMinutes == -1)
18958 throw Exception(
"IncMinutes -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
18960 if(FirstServiceTime == TDateTime(-1))
18962 throw Exception(
"First service time -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
18966 if(!Arrival && (Time2 == CDTTime))
18971 if(Arrival && (Time2 == CDTTime))
18975 if(Time2 > CDTTime)
18980 if(Time2 < CDTTime)
18995 LP1 = List1.begin();
18997 for(ListPtr1 = LocPtr1; ListPtr1 != LP1; ListPtr1--)
18999 if(ListPtr1 == List1.begin())
19003 if(ListPtr1->SubString(1, 3) ==
"%%%")
19010 LP2 = List2.begin();
19012 for(ListPtr2 = LocPtr2; ListPtr2 != LP2; ListPtr2--)
19014 if(ListPtr2 == List2.begin())
19018 if(ListPtr2->SubString(1, 3) ==
"%%%")
19028 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
19030 if(ListPtr1 == LocPtr1)
19034 if(ListPtr1->SubString(1, 3) ==
"%%%")
19038 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
19040 if(ListPtr2 == LocPtr2)
19044 if(ListPtr2->SubString(1, 3) ==
"%%%")
19048 if((*ListPtr1) == (*ListPtr2))
19065 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
19067 if(ListPtr1 == List1.end())
19071 if(ListPtr1->SubString(1, 3) ==
"%%%")
19075 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
19077 if(ListPtr2 == List2.end())
19081 if(ListPtr2->SubString(1, 3) ==
"%%%")
19085 if((*ListPtr1) == (*ListPtr2))
19102 if(ExitList.empty())
19108 AnsiString ExitLocList =
"";
19111 unsigned int Counter = 0;
19112 for(
TNumListIterator ELIt = ExitList.begin(); ELIt != ExitList.end(); ELIt++)
19116 if(((Counter % 6) == 0) && (Counter < (ExitList.size() - 1)))
19118 ExitLocList +=
"\n";
19121 if(StartName ==
"")
19123 if(ExitList.size() == 1)
19127 return(
" at " + ID);
19132 if(ExitList.size() < 4)
19134 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
19139 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
19144 for(
TNumListIterator ELIT = ExitList.begin(); ELIT != ExitList.end(); ELIT++)
19149 if(ExitList.size() < 4)
19151 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
19156 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
19162 if(ExitList.size() < 4)
19164 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
19165 return(
" at " + StartName);
19169 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
19170 return(
" at " + StartName);
19210 AnsiString FormatStr =
"####0.0";
19211 AnsiString AvLateArrMins =
"";
19212 AnsiString AvEarlyArrMins =
"";
19213 AnsiString AvLatePassMins =
"";
19214 AnsiString AvEarlyPassMins =
"";
19215 AnsiString AvLateDepMins =
"";
19216 AnsiString AvLateExitMins =
"";
19217 AnsiString AvEarlyExitMins =
"";
19247 PerfFile <<
'\n' <<
'\n' <<
"***************************************";
19248 PerfFile <<
'\n' <<
'\n' <<
"Performance summary:" <<
'\n';
19260 PerfFile <<
LateArrivals <<
" late arrivals (average " << AvLateArrMins.c_str() <<
" min)" <<
'\n';
19264 PerfFile <<
LateArrivals <<
" late arrival (" << AvLateArrMins.c_str() <<
" min)" <<
'\n';
19272 PerfFile <<
EarlyArrivals <<
" early arrivals (average " << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
19276 PerfFile <<
EarlyArrivals <<
" early arrival (" << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
19284 PerfFile <<
OnTimePasses <<
" on-time passes" <<
'\n';
19292 PerfFile <<
LatePasses <<
" late passes (average " << AvLatePassMins.c_str() <<
" min)" <<
'\n';
19296 PerfFile <<
LatePasses <<
" late pass (" << AvLatePassMins.c_str() <<
" min)" <<
'\n';
19300 PerfFile <<
LatePasses <<
" late passes" <<
'\n';
19304 PerfFile <<
EarlyPasses <<
" early passes (average " << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
19308 PerfFile <<
EarlyPasses <<
" early pass (" << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
19312 PerfFile <<
EarlyPasses <<
" early passes" <<
'\n';
19317 PerfFile <<
OnTimeExits <<
" on-time exits" <<
'\n';
19321 PerfFile <<
OnTimeExits <<
" on-time exit" <<
'\n';
19325 PerfFile <<
LateExits <<
" late exits (average " << AvLateExitMins.c_str() <<
" min)" <<
'\n';
19329 PerfFile <<
LateExits <<
" late exit (" << AvLateExitMins.c_str() <<
" min)" <<
'\n';
19333 PerfFile <<
LateExits <<
" late exits" <<
'\n';
19337 PerfFile <<
EarlyExits <<
" early exits (average " << AvEarlyExitMins.c_str() <<
" min)" <<
'\n';
19341 PerfFile <<
EarlyExits <<
" early exit (" << AvEarlyExitMins.c_str() <<
" min)" <<
'\n';
19345 PerfFile <<
EarlyExits <<
" early exits" <<
'\n';
19350 PerfFile <<
OnTimeDeps <<
" on-time departures" <<
'\n';
19354 PerfFile <<
OnTimeDeps <<
" on-time departure" <<
'\n';
19358 PerfFile <<
LateDeps <<
" late departures (average " << AvLateDepMins.c_str() <<
" min)" <<
'\n';
19362 PerfFile <<
LateDeps <<
" late departure (" << AvLateDepMins.c_str() <<
" min)" <<
'\n';
19366 PerfFile <<
LateDeps <<
" late departures" <<
'\n';
19368 TDateTime TempExcessLCDownTime;
19382 if(TempExcessLCDownTime > TDateTime(0))
19388 AnsiString FormattedExcessLCDownMins = FormatFloat(FormatStr,
ExcessLCDownMins);
19392 PerfFile << FormattedExcessLCDownMins.c_str() <<
" excess minutes of level crossing barrier down time" <<
'\n';
19396 PerfFile <<
MissedStops <<
" missed stops" <<
'\n';
19400 PerfFile <<
MissedStops <<
" missed stop" <<
'\n';
19436 PerfFile <<
NumFailures <<
" train failures" <<
'\n';
19440 PerfFile <<
NumFailures <<
" train failure" <<
'\n';
19446 PerfFile <<
AvHoursIntValue <<
" hour mean time betweeen train failures" <<
'\n';
19450 PerfFile <<
AvHoursIntValue <<
" hours mean time betweeen train failures" <<
'\n';
19453 AnsiString AvLateMinsLocsNotReached =
"";
19459 if(LocsNotReached > 0)
19462 PerfFile << LocsNotReached <<
" locations that trains failed to reach (average lateness " << AvLateMinsLocsNotReached.c_str() <<
" min)" <<
'\n';
19466 PerfFile <<
SPADRisks <<
" SPAD risks" <<
'\n';
19470 PerfFile <<
SPADRisks <<
" SPAD risk" <<
'\n';
19482 PerfFile <<
Derailments <<
" derailments" <<
'\n';
19486 PerfFile <<
Derailments <<
" derailment" <<
'\n';
19496 PerfFile <<
'\n' <<
"***************************************" <<
'\n';
19498 bool DerailSPADFlag =
false, CrashFlag =
false;
19500 int OverallScorePercent = 100;
19501 int TotArrDepExit = 0;
19502 double TotLateMinsFactor = 1;
19503 double MissedStopAndSPADRiskFactor = 1;
19504 double NetNegFactor = 1;
19514 OverallScorePercent = 5;
19515 DerailSPADFlag =
true;
19519 OverallScorePercent = 0;
19522 if(OverallScorePercent == 100)
19524 if(TotArrDepExit > 0)
19526 TotLateMinsFactor =
19534 NetNegFactor = TotLateMinsFactor * MissedStopAndSPADRiskFactor;
19536 OverallScorePercent = 100 * NetNegFactor;
19539 if((TotArrDepExit > 0) || DerailSPADFlag || CrashFlag)
19542 AnsiString OneFailureString =
", though the failure would account for some poor performance";
19543 AnsiString TwoOrMoreFailureString =
", though the failures would account for some poor performance";
19544 AnsiString AddedString =
"";
19547 AddedString = OneFailureString;
19551 AddedString = TwoOrMoreFailureString;
19553 PerfFile <<
"\nOverall score: " << OverallScorePercent <<
"%\n";
19554 AnsiString Rating =
"";
19555 if(OverallScorePercent == 100)
19557 Rating =
"Perfect!";
19559 else if(OverallScorePercent >= 95)
19561 Rating =
"Excellent";
19563 else if(OverallScorePercent >= 90)
19565 Rating =
"Very good";
19567 else if(OverallScorePercent >= 80)
19571 else if(OverallScorePercent >= 70)
19575 else if(OverallScorePercent >= 60)
19577 Rating =
"Unacceptable" + AddedString;
19579 else if(OverallScorePercent >= 50)
19581 Rating =
"Poor" + AddedString;
19583 else if(OverallScorePercent >= 40)
19585 Rating =
"Bad" + AddedString;
19587 else if(OverallScorePercent >= 30)
19589 Rating =
"Very bad" + AddedString;
19591 else if(OverallScorePercent >= 20)
19593 Rating =
"Terrible" + AddedString;
19595 else if(OverallScorePercent >= 10)
19597 Rating =
"Appalling" + AddedString;
19599 else if(OverallScorePercent >= 5)
19603 Rating =
"Disastrous - potential loss of life";
19608 Rating =
"Dire" + AddedString;
19611 else if(OverallScorePercent < 5)
19615 Rating =
"Catastrophic - loss of life";
19619 Rating =
"Abysmal";
19622 PerfFile <<
"Overall rating: " << Rating.c_str() <<
'\n';
19626 PerfFile <<
"\nThere were no timetabled departures, arrivals or exits so there is insufficient information to provide a performance score or rating" <<
'\n';
19628 PerfFile <<
'\n' <<
"***************************************";
19637 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
19687 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
19722 int IncrementalMinutes = 0;
19736 bool TrainOperatingFlag =
false;
19741 TrainOperatingFlag =
true;
19745 if(TrainOperatingFlag)
19753 for(
unsigned int z = 0; z < TDEntry.
ActionVector.size(); z++)
19800 AnsiString HeadCode;
19804 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
19808 HCandTrainPosParam.first = HeadCode;
19809 HCandTrainPosParam.second = TrainID;
19811 if((TimeToAct >= 0) && (TimeToAct < 59.9))
19814 OpTimeToActMultiMapEntry.first = TimeToAct;
19815 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
19844 float TimeToAct = 0;
19845 int DistanceToRedSignal = 0;
19848 ContinuationEntryVecPosVector.clear();
19849 bool LaterTrain =
false;
19853 LaterTrain =
false;
19854 if(CTEIt->second.TrainDataEntryPtr->TrainOperatingDataVector.at(CTEIt->second.RepeatNumber).RunningEntry !=
NotStarted)
19865 if(!ContinuationEntryVecPosVector.empty())
19867 for(
unsigned int x = 0; x < ContinuationEntryVecPosVector.size(); x++)
19869 if(CTEIt->second.VectorPosition == ContinuationEntryVecPosVector.at(x))
19883 ContinuationEntryVecPosVector.push_back(CTEIt->second.VectorPosition);
19884 AnsiString HeadCode = CTEIt->second.HeadCode;
19885 float CurrentStopTime;
19886 float LaterStopTime;
19887 float RecoverableTime;
19890 int DistanceToExit;
19892 bool SigControlAndCanPassRedSignal =
false;
19900 if(CTEIt->second.TrainDataEntryPtr->ActionVector.size() == 1)
19906 SigControlAndCanPassRedSignal, &CTEIt->second.TrainDataEntryPtr->ActionVector.at(AtValue),
19907 HeadCode, TrainID, CurrentStopTime, LaterStopTime, RecoverableTime, AvTrackSpeed, DistanceToExit, ExitPair);
19910 if(AvTrackSpeed < 30)
19914 if(DistanceToRedSignal == -1)
19920 int Speed = AvTrackSpeed;
19921 int MaxSpeed = int(CTEIt->second.TrainDataEntryPtr->MaxRunningSpeed);
19922 if(AvTrackSpeed > MaxSpeed)
19926 if(CTEIt->second.TrainDataEntryPtr->ActionVector.at(0).SignallerControl)
19929 Speed = CTEIt->second.TrainDataEntryPtr->SignallerSpeed;
19932 TimeToAct = LaterStopTime + DistanceToRedSignal * 3.6 / 60 / Speed;
19937 float MinsBefEnter = double(CTEIt->first -
TTClockTime) * 86400.0 / 60.0;
19938 TimeToAct += MinsBefEnter;
19941 HCandTrainPosParam.first = HeadCode;
19942 HCandTrainPosParam.second = -1 - CTEIt->second.VectorPosition;
19945 if(TimeToAct < 59.9)
19947 OpTimeToActMultiMapEntry.first = TimeToAct;
19948 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
19973 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
19983 TimeToExitMultiMapEntry.first = ExitPair;
19984 TimeToExitMultiMapEntry.second = ExitInfo;
19994 bool SigControlAndCanPassRedSignal,
TActionVectorEntry *AVPtr, AnsiString HeadCode,
int TrainID,
float &CurrentStopTime,
float &LaterStopTime,
19995 float &RecoverableTime,
int &AvTrackSpeed,
int &DistanceToExit,
THVShortPair &ExitPair)
20004 AnsiString(TrackVectorPositionEntryPos) +
", " + AVPtr->
Command);
20005 int DistanceToRedSignal = 0;
20006 DistanceToExit = -1;
20007 ExitPair.first = -1;
20008 ExitPair.second = -1;
20009 int CumTrackSpeed = 0;
20011 int TrackSpeedCount = 0;
20012 float KmPerLocationStop;
20013 float MaxAllowableSpeed;
20023 int CurrentElement = TrackVectorPosition;
20024 int CurrentEntryPos = TrackVectorPositionEntryPos;
20029 CurrentStopTime = 0;
20031 RecoverableTime = 0;
20032 if(CurrentElement == -1)
20037 int CurrentExitPos;
20042 if((CurrentEntryPos == 0) || (CurrentEntryPos == 2))
20046 CurrentExitPos = 1;
20050 CurrentExitPos = 3;
20055 CurrentExitPos = 0;
20091 CurrentStopTime = float(TimeToDepart);
20097 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
20108 else if(SigControlAndCanPassRedSignal)
20113 if((NextEntryPos == 0) || (NextEntryPos == 2))
20134 CurrentElement = NextElement;
20135 CurrentEntryPos = NextEntryPos;
20136 CurrentExitPos = NextExitPos;
20148 int LaterStopNumber = 0;
20152 while(!((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0)))
20161 if(CurrentEntryPos > 1)
20176 DistanceToExit = DistanceToRedSignal;
20181 if(TrackSpeedCount > 0)
20183 MaxAllowableSpeed = CumTrackSpeed / TrackSpeedCount;
20187 if(CurrentEntryPos > 1)
20198 if(LaterStopNumber > 0)
20200 KmPerLocationStop = float(DistanceToRedSignal) / LaterStopNumber / 1000;
20201 AvTrackSpeed = (8.75 * KmPerLocationStop) + 44;
20207 AvTrackSpeed = (sqrt(
float(DistanceToRedSignal) / 1000) * 44) + 60;
20211 if(AvTrackSpeed > MaxAllowableSpeed)
20213 AvTrackSpeed = MaxAllowableSpeed;
20225 bool StopRequired =
false;
20242 int TrainOnElement;
20249 if(CurrentEntryPos > 1)
20258 if((TrainOnElement > -1) && (TrainOnElement != TrainID))
20267 double StopTimeDouble;
20280 if(StopTimeDouble < 0.5)
20282 StopTimeDouble = 0.5;
20286 LaterStopTime += float(StopTimeDouble);
20287 RecoverableTime += StopTimeDouble - 0.5;
20288 if((LaterStopNumber == 1) && (TrainID > -1))
20296 if((AVPtr + 1)->FormatType ==
TimeLoc)
20300 StopTimeDouble = double((AVPtr + 1)->DepartureTime - AVPtr->
ArrivalTime) * 86400.0 / 60.0;
20302 if(StopTimeDouble < 0.5)
20304 StopTimeDouble = 0.5;
20307 LaterStopTime += float(StopTimeDouble);
20308 RecoverableTime += StopTimeDouble - 0.5;
20309 if((LaterStopNumber == 1) && (TrainID > -1))
20325 if(NextElement == -1)
20334 if((NextEntryPos == 0) || (NextEntryPos == 2))
20355 CurrentElement = NextElement;
20356 CurrentEntryPos = NextEntryPos;
20357 CurrentExitPos = NextExitPos;
20361 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
20374 if(TrackSpeedCount > 0)
20376 MaxAllowableSpeed = CumTrackSpeed / TrackSpeedCount;
20380 if(CurrentEntryPos > 1)
20391 if(LaterStopNumber > 0)
20393 KmPerLocationStop = float(DistanceToRedSignal) / LaterStopNumber / 1000;
20394 AvTrackSpeed = (8.75 * KmPerLocationStop) + 44;
20400 AvTrackSpeed = (sqrt(
float(DistanceToRedSignal) / 1000) * 44) + 60;
20404 if(AvTrackSpeed > MaxAllowableSpeed)
20406 AvTrackSpeed = MaxAllowableSpeed;
20409 return(DistanceToRedSignal);